第八部分属性表和向导Word文件下载.docx

上传人:b****6 文档编号:16507724 上传时间:2022-11-24 格式:DOCX 页数:21 大小:730.97KB
下载 相关 举报
第八部分属性表和向导Word文件下载.docx_第1页
第1页 / 共21页
第八部分属性表和向导Word文件下载.docx_第2页
第2页 / 共21页
第八部分属性表和向导Word文件下载.docx_第3页
第3页 / 共21页
第八部分属性表和向导Word文件下载.docx_第4页
第4页 / 共21页
第八部分属性表和向导Word文件下载.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

第八部分属性表和向导Word文件下载.docx

《第八部分属性表和向导Word文件下载.docx》由会员分享,可在线阅读,更多相关《第八部分属性表和向导Word文件下载.docx(21页珍藏版)》请在冰豆网上搜索。

第八部分属性表和向导Word文件下载.docx

有两个类,CPropertySheetWindow和CPropertySheetImpl,它们组合起来实现了属性表。

它们都定义在atldlgs.h头文件中。

CPropertySheetWindow是一个窗口接口类,也就是说,它派生于CWindow,而CPropertySheetImpl具有消息映射并实际上实现了窗口功能。

这与基本的ATL窗口类是一致的,在其中CWindow和CWindowImpl也被一起使用。

CPropertySheetWindow包括了对多个PSM_*消息的封装,比如SetActivePageByID()就封装了PSM_SETCURSELID。

CPropertySheetImpl管理着一个PROPSHEETHEADER结构以及一组HPROPSHEETPAGE。

CPropertySheetImpl中还有一些方法,用于设置某些PROPSHEETHEADER域,添加以及删除页。

你也可以通过访问m_psh成员变量来获得对PROPSHEETHEADER的直接访问。

最后要说明的是,CPropertySheet是CPropertySheetImpl的一个特化,如果你根本不需要对属性表进行定制的话,那你就可以使用它。

CPropertySheetImpl的方法

下面是CPropertySheetImpl的一些重要的方法。

因为许多方法仅仅是对窗口消息的封装,我不会在这儿列一个详尽的清单,但你可以到atldlgs.h里查看方法的完整列表。

CPropertySheetImpl(_U_STRINGorIDtitle=(LPCTSTR)NULL,

UINTuStartPage=0,HWNDhWndParent=NULL)

CPropertySheetImpl的构造函数允许你当下就指定一些常用的属性,这样你就不必在以后调用别的方法来设置它们。

title指定了在属性表的标题上用到的文字。

_U_STRINGorID是一个WTL辅助类,可以使你传递LPCTSTR或者字符串资源ID。

例如,如果IDS_SHEET_TITLE是字符串表中某个字符串的ID的话,那么下面这两行就都可以工作:

CPropertySheetImplmySheet(IDS_SHEET_TITLE);

CPropertySheetImplmySheet(_T("

Mypropsheet"

));

uStartPage是从零开始的页面索引值,当属性表第一次显示时,该页就会被激活。

hWndParent设置了属性表的父窗口。

BOOLAddPage(HPROPSHEETPAGEhPage)

BOOLAddPage(LPCPROPSHEETPAGEpPage)

向属性表中添加一个属性页。

如果该页已经创建的话,你可以将其句柄(一个HPROPSHEETPAGE)传递给第一个重载版本的函数。

更常见的方法是使用第二个重载版本。

使用这一版本,你可以先设置一个PROPSHEETPAGE结构(此事可以由CPropertyPageImpl来做,后文会有介绍),而CPropertySheetImpl会为你创建并管理该页。

BOOLRemovePage(HPROPSHEETPAGEhPage)

BOOLRemovePage(intnPageIndex)

从属性表中删除一个属性页。

你既可以传递属性页的句柄也可以传递基于零的索引值。

BOOLSetActivePage(HPROPSHEETPAGEhPage)

BOOLSetActivePage(intnPageIndex)

设置属性表的活动属性页。

你既可以传递要激活的页的句柄,也可以传递基于零的索引。

你也可以在创建属性表之前调用此方法,以设置属性表首次显示时要激活哪一页。

voidSetTitle(LPCTSTRlpszText,UINTnStyle=0)

设置属性表标题使用的文字。

nStyle可以是0或者PSH_PROPTITLE。

如果是PSH_PROPTITLE,则此风格会被加到属性表上,就会使“Propertiesfor”字样附加到你在lpszText参数里传入的文本之前。

voidSetWizardMode()

设置PSH_WIZARD风格,这会使得属性表变成一个向导。

你必须在显示属性表之前调用此方法。

voidEnableHelp()

设置PSH_HASHELP风格,它会为属性表加入帮助按钮。

注意,你还需要在为此按钮提供帮助的各个页中启用帮助才能有效。

INT_PTRDoModal(HWNDhWndParent=:

:

GetActiveWindow())

创建并显示一个模态属性表。

正的返回值表示成功,对于返回值的完整描述可以参看PropertySheet()API的文档。

如果有错误发生且属性表没有创建成功,DoModal()会返回-1。

HWNDCreate(HWNDhWndParent=NULL)

创建并显示一个非模态的属性表,并返回其窗口句柄。

如果发生了错误,属性表就创建不出来,Create()会返回NULL。

WTL属性页类

和属性表类相似,此WTL类封装了属性页的相关工作,也是既有一个窗口接口类,CPropertyPageWindow,又有一个实现类CPropertyPageImpl。

CPropertyPageWindow非常小,其包含的大部分辅助函数都调用了父表中的方法。

CPropertyPageImpl派生于CDialogImplBaseT,这是因为一个属性页是用一个对话框资源来构建的。

这也意味着,我们在对话框里所用到的所有WTL特性在属性表中都是可用的,比如说DDX和DDV。

CPropertyPageImpl有两个主要的目的:

管理保存在成员变量m_psp中的PROPSHEETPAGE结构,并处理PSN_*通知消息。

对于非常简单的属性页,你可以使用CPropertyPage类。

这仅仅适用于那些根本不与用户交互的页,比方说一个About页,或者是向导里的简介页面。

你还可以创建掌控ActiveX控件的页。

首先,你要把atlhost.h包含到stdafx.h中去,而对于该页,你要使用CAxPropertyPageImpl代替CPropertyPageImpl。

对于要掌控ActiveX控件的简单页,你可以使用CAxPropertyPage来代替CPropertyPage。

CPropertyPageWindow的方法

CPropertyPageWindow最重要的方法是GetPropertySheet():

CPropertySheetWindowGetPropertySheet()

此方法获取属性页的父窗口(也即属性表)的HWND并将之关联到一个CPropertySheetWindow上。

再把新的CPropertySheetWindow返回给调用者。

请注意,此处只是创建一个临时对象,它并不是返回用来创建属性表的实际的CPropertySheet或者CPropertySheetImpl对象的指针或者是引用。

如果你是使用自己的CPropertySheetImpl派生类,而又要在属性表对象中访问数据成员的话,这一点就很重要。

剩下的成员仅仅是调用封装了PSM_*消息的CPropertySheetWindow函数:

BOOLApply()

voidCancelToClose()

voidSetModified(BOOLbChanged=TRUE)

LRESULTQuerySiblings(WPARAMwParam,LPARAMlParam)

voidRebootSystem()

voidRestartWindows()

voidSetWizardButtons(DWORDdwFlags)

例如,在CPropertyPageImpl派生类里,你可以调用:

SetWizardButtons(PSWIZB_BACK|PSWIZB_FINISH);

用以代替:

CPropertySheetWindowwndSheet;

wndSheet=GetPropertySheet();

wndSheet.SetWizardButtons(PSWIZB_BACK|PSWIZB_FINISH);

CPropertyPageImpl的方法

CPropertyPageImpl管理着一个PROPSHEETPAGE结构,即其公用成员m_psp。

CPropertyPageImpl还有一个operatorPROPSHEETPAGE*转换器,因此你可以把一个CPropertyPageImpl传递到接受LPPROPSHEETPAGE或者LPCPROPSHEETPAGE参数的方法里,比如CPropertySheetImpl:

AddPage()。

CPropertyPageImpl的构造函数允许你设置页的标题,也即出现在页的标签上的文字:

CPropertyPageImpl(_U_STRINGorIDtitle=(LPCTSTR)NULL)

如果你需要手动创建一个页,而不是让属性表来干这件事的话,你可以调用Create():

HPROPSHEETPAGECreate()

Create()只不过是使用m_psp作为参数调用了CreatePropertySheetPage()。

你只有在以下情况下才需要调用Create(),或者是在属性表创建之后需要向其上添加一个页,或者是要把创建的页传递给其他不受你控制的属性表,例如,一个属性表处理器的外壳扩展。

还有三个方法,可以设置页面内的几处标题文字:

voidSetTitle(_U_STRINGorIDtitle)

voidSetHeaderTitle(LPCTSTRlpstrHeaderTitle)

voidSetHeaderSubTitle(LPCTSTRlpstrHeaderSubTitle)

第一个函数用于改变该页的标签上的文字。

其他的两个用在Wizard97风格的向导中,用于设置属性页上方的题头区域内的文字。

在m_psp中设置PSP_HASHELP标志,当页面激活时即可以启用Help按钮。

处理通知消息

CPropertyPageImpl中有一个消息映射,它处理了WM_NOTIFY。

如果通知代码是一个PSN_*值,OnNotify()会调用用于此通知的特定的处理器。

这由编译时虚函数技术完成,因而在派生类里可以很轻易地覆盖该处理器。

共有两组通知处理器,这是由于WTL3和7之间出现了设计上的变化。

在WTL3里,通知处理器会返回一个不同于PSN_*消息的返回值的值。

比如,WTL3中PSN_WIZFINISH的处理器:

casePSN_WIZFINISH:

lResult=!

pT->

OnWizardFinish();

break;

OnWizardFinish()希望返回TRUE以允许向导结束,或者返回FALSE来阻止向导的关闭;

但是,由于IE5的公用控件添入了可以从PSN_WIZFINISH的处理器返回一个窗口句柄的能力用以设置焦点,所以这就行不通了。

WTL3的应用不能使用此特性,因为所有的非零值都被认为是一样的。

在WTL7里,OnNotify()不会改变从PSN_*处理器返回的任何值。

处理器可以返回任何文档化的合法值,因而其行为也就完全正常了。

但是,出于后向兼容的考虑,WTL3的处理器仍然存在并且被缺省使用。

要使用WTL7的处理器,你必须把下列行添加到stdafx.h中,而且位于atldlgs.h的包含语句之前:

#define_WTL_NEW_PAGE_NOTIFY_HANDLERS

在写新代码的时候,显然没有什么理由不使用WTL7的处理器,所以在这就不介绍WTL3的处理器了。

CPropertyPageImpl对所有的通知都有缺省的处理器,所以你可以只覆盖和你的程序相关的那些处理器。

缺省处理器及其行为如下:

intOnSetActive()-允许属性页成为活动的

BOOLOnKillActive()-允许属性页成为非活动的

intOnApply()-返回表示应用操作已成功的PSNRET_NOERROR

voidOnReset()-无操作

BOOLOnQueryCancel()-允许取消操作

intOnWizardBack()-到上一页

intOnWizardNext()-到下一页

INT_PTROnWizardFinish()-允许向导结束

voidOnHelp()-无操作

BOOLOnGetObject(LPNMOBJECTNOTIFYlpObjectNotify)-无操作

intOnTranslateAccelerator(LPMSGlpMsg)-返回表示消息没有被处理的PSNRET_NOERROR

HWNDOnQueryInitialFocus(HWNDhWndFocus)-返回NULL以把焦点设置到Tab顺序里的第一个控件上

创建一个属性表

现在,我们有关类的介绍就结束了,我们需要有一个程序来演示如何使用它们。

本章的示例工程是一个简单的SDI应用,它在其客户区要显示一个图片,并使用颜色填充背景。

图片和颜色可以通过选项对话框(一个属性表)以及一个向导(后文叙述)来更改。

永远最简单的属性表

使用WTLAppWizard生成一个SDI工程后,我们就可以开始创建用于About框的属性表了。

我们首先从向导为我们生成的about对话框开始,要改变其风格才能使它像一个属性页一样工作。

第一步是移除OK按钮,在属性表里它没有任何意义。

在对话框的属性里,将Style改为Child,将Border改为Thin,并选中Disabled。

第二步,也是最后一步,是在OnAppAbout()处理器中创建属性表。

我们可以使用不可定制的CPropertySheet和CPropertyPage来做这件事:

voidCMainFrame:

OnAppAbout(...)

{

CPropertySheetsheet(_T("

AboutPSheets"

CPropertyPage<

IDD_ABOUTBOX>

pgAbout;

sheet.AddPage(pgAbout);

sheet.DoModal(*this);

}

结果看起来是这样的:

创建一个有用的属性页

因为并不是每个属性表的属性页都和About框一样简单,所以大部分的页都会需要是一个CPropertyPageImpl的派生类,所以我们现在就来看一下这样的一个类。

我们要创建一个新的属性页,其中包含了显示在客户区背景中的图象的设置。

对话框如下:

此对话框和About页的风格一样。

对于此页,我们需要一个新类,将其命名为CBackgroundOptsPage。

此类派生于CPropertyPageImpl,因为它毕竟是一个属性页,同时也派生于CWinDataExchange,这样可以启用DDX。

classCBackgroundOptsPage:

publicCPropertyPageImpl<

CBackgroundOptsPage>

publicCWinDataExchange<

public:

enum{IDD=IDD_BACKGROUND_OPTS};

//Construction

CBackgroundOptsPage();

~CBackgroundOptsPage();

//Maps

BEGIN_MSG_MAP(CBackgroundOptsPage)

MSG_WM_INITDIALOG(OnInitDialog)

CHAIN_MSG_MAP(CPropertyPageImpl<

END_MSG_MAP()

BEGIN_DDX_MAP(CBackgroundOptsPage)

DDX_RADIO(IDC_BLUE,m_nColor)

DDX_RADIO(IDC_ALYSON,m_nPicture)

END_DDX_MAP()

//Messagehandlers

BOOLOnInitDialog(HWNDhwndFocus,LPARAMlParam);

//Propertypagenotificationhandlers

intOnApply();

//DDXvariables

intm_nColor,m_nPicture;

};

此类中需要注意的有:

∙其中有一个名为IDD的公用成员,里面存放着相关联的对话框资源ID。

∙其消息映射与CDialogImpl类相似。

∙消息映射会把消息串联到CPropertyPageImpl,从而可以处理属性表相关的消息。

∙其中有一个OnApply()处理器,当用户点击属性表上的OK时可以保存用户的选择。

OnApply()相当简单,它调用DoDataExchange()来更新DDX变量,然后再返回一个代码,指示属性表是否可以关闭:

intCBackgroundOptsPage:

OnApply()

returnDoDataExchange(true)?

PSNRET_NOERROR:

PSNRET_INVALID;

添加一个Tools|Options菜单项,让它来把属性表搬出来,我们把此命令的处理器放到视图类中。

此处理器像前面一样创建属性表,不过要把新的CBackgroundOptsPage添加到属性表里。

voidCPSheetsView:

OnOptions(UINTuCode,intnID,HWNDhwndCtrl)

PSheetsOptions"

),0);

CBackgroundOptsPagepgBackground;

pgBackground.m_nColor=m_nColor;

pgBackground.m_nPicture=m_nPicture;

sheet.m_psh.dwFlags|=PSH_NOAPPLYNOW|PSH_NOCONTEXTHELP;

sheet.AddPage(pgBackground);

if(IDOK==sheet.DoModal())

SetBackgroundOptions(pgBackground.m_nColor,

pgBackground.m_nPicture);

sheet的构造函数的第二个参数现在是0,这表示在开始的时候应该看到索引为0的页。

你可以把此值改为1使得属性表出现时首先看到的是About页。

因为这仅仅是演示代码,我计划偷个懒,让CBackgroundOptsPage中连接到单选按钮的变量成为共有的。

视图会把当前的选项存放在这些变量里,如果用户点击了属性表的OK,那就把这些新的值保存起来。

如果用户点击了OK,DoModal()会返回IDOK,于是视图就会使用的新的图片和颜色重绘自己。

下面是不同视图的屏幕截图:

创建一个更好的属性表类

OnOptions()处理器创建的属性表确实不错,但是那一大堆设置和初始化代码,却不应该是CMainFrame的职责。

更好的方法是从CPropertySheetImpl派生一个类,由它来处理这些工作。

#include"

BackgroundOptsPage.h"

classCOptionsSheet:

publicCPropertySheetImpl<

COptionsSheet>

COptionsSheet(_U_STRINGorIDtitle=(LPCTSTR)NULL,

UINTuStartPage=0,HWNDhWndParent=NULL);

BEGIN_MSG_MAP(COptionsSheet)

CHAIN_MSG_MAP(CPropertySheetImpl<

//Propertypages

CBackgroundOptsPagem_pgBackground;

CPropertyPage<

m_pgAbout;

有了这个类,我们就把诸如表中有哪些页之类的细节移到了属性表自身里。

构造函数处理以下事宜:

把属性页添加到属性表里,并设置其它必要的标志:

COptionsSheet:

CAppPropertySheet(

_U_STRINGorIDtitle,UINTuStartPage,HWNDhWndParent):

CPropertySheetImpl<

(title,uStartPage,hWndParent)

m_psh.dwFlags|=PSH_NOAPPLY

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 社交礼仪

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1