Aero 向导体现了向导界面自从在 Windows 95 操作系统家族中首次推广以来的演变。它们为普通的向导界面提供了崭新的外观,而且被设计为可以为用户提供更专注的体验。在本 Windows Vista for Developers 系列的这第一个部分里,我将向你展示如何你就可以使用少量的代码把一个简单的向导转换为一个 Aero 向导。
属性表
扼要地讲,向导其实只是属性表的一个变体,属性表由 PROPSHEETHEADER 结构来定义而由 PropertySheet 函数实现。ATL 提供了 CPropertySheetImpl 类模板来生成使用 PropertySheet 函数牵涉到的许多代码。我们从一个简单的属性表开始,然后再看怎样把它改变为一个 Aero 向导:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
class SampleWizard : public CPropertySheetImpl<SampleWizard> { public: BEGIN_MSG_MAP(SampleWizard) CHAIN_MSG_MAP(__super) END_MSG_MAP() SampleWizard() : CPropertySheetImpl<SampleWizard>(IDS_TITLE) { VERIFY(AddPage(m_page)); } private: SamplePage m_page; }; |
SampleWizard 类派生于上述的 CPropertySheetImpl 类模板,该类模板提供了属性表的大部分功能。消息映射简单地把消息导向基类。构造函数调用了基类的构造函数以设置向导的标题,并使用继承自 CPropertySheetImpl 的 AddPage 方法向向导中添加了一个页面. SamplePage 类具有如下定义:
1 2 3 4 5 6 7 8 9 10 11 12 |
class SamplePage : public CPropertyPageImpl<SamplePage> { public: BEGIN_MSG_MAP(SamplePage) CHAIN_MSG_MAP(__super) END_MSG_MAP() enum { IDD = IDD_SAMPLE_PAGE }; }; |
SamplePage 类派生于 CPropertyPageImpl 类模板,该类模板提供了属性页的大部分功能。它也有一个简单的消息映射把消息都导向基类。一个 enum 定义了基类中所期望的 IDD 常量,用以标识属性页用到的对话框资源。
现在,你就可以用下列简单代码创建并显示一个模态属性表了:
1 2 |
SampleWizard sampleWizard; sampleWizard.DoModal(); |
第一行创建了 SampleWizard 对象,其中,各个基类会负责构造调用 PropertySheet 函数所需的结构。SampleWizard 继承自 CPropertySheetImpl 类模板的 DoModal 方法则负责调用 PropertySheet 函数。其结果就是一个简单的属性表:
经典向导
要把属性表变为一个经典的向导,你所需的全部工作就是把下列语句添加到 SampleWizard 的构造函数中:
1 |
m_psh.dwFlags |= PSH_WIZARD97; |
它所做的就是把 PSH_WIZARD97 标志合并到已经在 PROPSHEETHEADER 结构里已经设置过的标志中。由于向导提供了一个额外的顶头区域,所以还要更新 SamplePage 类来指定此页的标头文字:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
class SamplePage : public CPropertyPageImpl<SamplePage> { public: BEGIN_MSG_MAP(SamplePage) CHAIN_MSG_MAP(__super) END_MSG_MAP() enum { IDD = IDD_BLANK_PAGE }; SamplePage() { VERIFY(m_title.LoadString(IDS_PAGE_TITLE)); SetHeaderTitle(m_title); } private: CString m_title; }; |
SamplePage 的构造函数使用继承于 CPropertyPageImpl 的 SetHeaderTitle 方法来设置页面的标头标题。要记住的是在页面的 PROPSHEETPAGE 结构里存储的是一个字符串指针,因此,字符串的生命期必须要超出构造函数。
经过这些适当的小改动,结果发生了相当引人注目的不同:
正如你可能注意到的,先前出现在标签上的文字已经把窗口标题替换了。
Aero 向导
现在,将 SampleWizard 构造函数中的 PSH_WIZARD97 替换为 PSH_AEROWIZARD,然后你就得到了新式的 Aero 向导界面:
你应该注意到窗口标题又变了回来而原来出现在属性表标签上的对话框标题已经不再使用了。
新消息
Aero 向导支持几个新的消息,用以更好地控制由向导提供的标准控件。
PSM_SHOWWIZBUTTONS 消息显示或者隐藏修饰向导的任意标准按钮。 PropSheet_ShowWizButtons 宏可以简化此消息的发送。使用它并不是特别的自然,不过一旦掌握了它,你就不该再有任何问题了。尽管只是一个宏,不过把它想象为一个如下定义的函数更有用(宏易于误解):
1 2 3 |
void PropSheet_ShowWizButtons(HWND handle, DWORD buttons, DWORD mask); |
handle 参数标识了向导窗口, buttons 参数指示要显示哪些按钮,而 mask 参数指示要操作哪些按钮。如果一个按钮标志同时出现于 buttons 和 masks 参数中则会被显示。如果一个按钮仅出现于 mask 参数中则会被隐藏。共有下列按钮标志可以使用:
1 2 3 4 |
PSWIZB_BACK PSWIZB_NEXT PSWIZB_FINISH PSWIZB_CANCEL |
例如,下面的调用将显示 Next 按钮而隐藏 Back 按钮:
1 2 3 |
PropSheet_ShowWizButtons(handle, PSWIZB_NEXT, PSWIZB_BACK | PSWIZB_NEXT); |
PSM_ENABLEWIZBUTTONS 消息启用或者禁用任意标准按钮。 PropSheet_EnableWizButtons 宏简化了此消息的发送:
1 2 3 |
void PropSheet_EnableWizButtons(HWND handle, DWORD buttons, DWORD mask); |
在如何标识按钮上此消息与 PSM_SHOWWIZBUTTONS 的工作方式是一致的。 buttons 参数指示那些按钮要启用或者禁用而 mask 参数指示要操作哪些按钮。例如,下列调用将启用 Next 按钮并禁用 Back 按钮。
1 2 3 |
PropSheet_EnableWizButtons(handle, PSWIZB_NEXT, PSWIZB_BACK | PSWIZB_NEXT); |
PSM_SETBUTTONTEXT 消息可以修改 Next、Finish 以及 Cancel 按钮的文字。 PropSheet_SetButtonText 宏简化了此消息的发送:
1 2 3 |
void PropSheet_SetButtonText(HWND handle, DWORD button, PCWSTR text); |
示例
为了让你能简单地试验 Aero 向导提供的各种选项,我创建了一个简单的向导工程你可以下载并用它进行实践:
阅读第二部分:深入任务对话框