WTL 的属性页类 WTL对属性页的封装类与属性表的封装类相似,有一个窗口接口类 CPropertyPageWindow 和一个实现类 CPropertyPageImpl 。CPropertyPageWindow 很小,包含最常用的需要在作为父窗口的属性表中调用的方法。
CPropertyPageImpl 是从 CDialogImplBaseT派生,由于属性页是从对话框资源中创建的,这就意味着所有可以在对话框中使用的WTL的特性都可以在属性页中使用,如DDX和DDV。CPropertyPageImpl 有两个主要作用:管理一个PROPSHEETPAGE数据结构(保存在成员变量m_psp中),处理所有PSN_开头的通知消息。对于很简单的属性页可以直接使用CPropertyPage类,这个类只适合与用户没有任何交互的属性页,例如“关于”页面或者向导中的介绍页面
也可以创建含有ActiveX控件的属性页。首先,这需要在stdafx.h文件中添加对atlhost.h的包含,还要使用CAxPropertyPageImpl代替CPropertyPageImpl。对于简单的页面可以使用CAxPropertyPage代替CPropertyPage。
CPropertyPageImpl 的方法 CPropertyPageImpl 管理着一个 PROPSHEETPAGE 结构,也就是公有成员 m_psp。CPropertyPageImpl还重载了PROPSHEETPAGE*操作符,所以你可以将CPropertyPageImpl传递给需要LPPROPSHEETPAGE 或 LPCPROPSHEETPAGE 类型的参数的方法,例如CPropertySheetImpl::AddPage()。
CPropertyPageImpl的构造函数允许你设置页面的标题,标题通常显示在页面的Tab标签上:
CPropertyPageImpl(_U_STRINGorID title = (LPCTSTR) NULL)
如果你不想让属性表创建属性页面而是想手工创建页面,你可以调用Create():
Create() 只是调用用m_psp做参数调用了 CreatePropertySheetPage() 。如果你向一个已经创建的属性表添加属性页或者向另一个不在控制的属性表添加属性页(例如,处理系统Shell扩展的属性表),那就只需要调用Create()函数。
下面的三个方法用于设置属性页的各种标题文本:
void SetTitle(_U_STRINGorID title) void SetHeaderTitle(LPCTSTR lpstrHeaderTitle) void SetHeaderSubTitle(LPCTSTR lpstrHeaderSubTitle) |
第一个方法改变页面标签的文字,另外几个用来设置Wizard97样式的向导中属性页顶部的文字。
设置m_psp中的PSP_HASHELP标志,当本页面激活时使属性表的帮助按钮可用。
处理通知消息 CPropertyPageImpl有一个消息映射处理WM_NOTIFY。如果通知代码是PSN_*的值,OnNotify()就会调用相应的通知处理函数。这使用了编译阶段虚函数机制,从而使得派生类可以很容易的重载这些处理函数。
由于WTL 3和WTL 7设计的改变,从而存在两套不同的通知处理机制。在WTL 3中通知处理函数返回的值与PSN_*消息的返回值不同,例如,WTL 3是这样处理PSN_WIZFINISH的:
case PSN_WIZFINISH: lResult = !pT->OnWizardFinish(); break; |
OnWizardFinish()期望返回TRUE结束向导,FALSE阻止关闭向导。这个方法很简陋,但是IE5的通用控件对PSN_WIZFINISH处理的返回值添加了新解释,他返回需要获得焦点的窗口的句柄。WTL 3的程序将不能使用这个特性,因为它对所有非0的返回值都做相同的处理。
在WTL 7中,OnNotify() 没有改变 PSN_* 消息的返回值,处理函数返回任何文档中规定的合法数值和正确的行为。当然,为了向前兼容,WTL 3 仍然使用当前默认的工作方式,要使用WTL 7的消息处理方式,你必须在中including atldlgs.h一行之前添加一行定义:
#define _WTL_NEW_PAGE_NOTIFY_HANDLERS |
编写新的代码没有理由不使用WTL 7的消息处理函数,所以这里就不介绍WTL 3的消息处理方式。
CPropertyPageImpl 为所有消息提供了默认的通知消息处理函数,你可以重载与你的程序有关的消息处理函数完成特殊的操作。默认的消息处理函数和相应的行为如下:
int OnSetActive() - 允许页面成为激活状态
BOOL OnKillActive() - 允许页面成为非激活状态
int OnApply() - 返回 PSNRET_NOERROR 表示应用操作成功完成
void OnReset() - 无相应的动作
BOOL OnQueryCancel() - 允许取消操作 int OnWizardBack() - 返回到前一个页面
int OnWizardNext() - 进行到下一个页面
INT_PTR OnWizardFinish() - 允许向导结束
void OnHelp() - 无相应的动作
BOOL OnGetObject(LPNMOBJECTNOTIFY lpObjectNotify) - 无相应的动作
int OnTranslateAccelerator(LPMSG lpMsg) - 返回 PSNRET_NOERROR 表示消息没有被处理
HWND OnQueryInitialFocus(HWND hWndFocus) - 返回 NULL 表示将按Tab Order顺序的第一个控件设为焦点状态