属性表
属性表是一个允许用户去查看和编辑项目的属性的窗口。例如,一个电子表格程序可能使用属性表去让用户设置字体和表格的边框属性,及设置设置的属性,例如一个磁盘驱动器,打印机或鼠标。
关于属性表
使用属性表
在Internet Explorer中属性表的更新
属性表手册
关于属性表
这个文档假设你已经十分的理解了对话框模板及对话框程序。如果不是这样,在继续下边的章节前你应该读一下平台SDK(Platform SDK)中的“对话框”(Dialog Boxes)。
要在你的应用程序中实现属性表,在你的项目中包含Prsht.h头文件。Prsht.h中包含了所有被属性表使用的标识符。
一个属性表包含的一个或多个层叠的窗口叫做页(pages),各自包含着一组相关属性的设置窗口。例如,一个页可以包含设置项目(item)字体的类型风格,大小,颜色等属性的控制。每页有一个标签(tab),用户可以使用它选择页,使用它移到属性表中的最显著的位置。下面的图解显示了一个查看和设置软盘驱动器属性的属性表。
属性表对话框
一个属性表和页实际上包含在对话框中。属性表是一个系统定义的对话框,它管理页及为它们提供一个公共容器。属性表对话框可以是模式的或非模式的。它包括一个框架,一个标题栏和四个按钮:确定(OK),取消(Cancel),应用(Apply Now)和帮助(Help)。(帮助(Help)按钮可能是被隐藏着的,象上面的图解)当用户单击了按钮时,对话框过程为页接收通知消息。
属性表中的每一页是应用程序定义的非模式对话在,它管理控制窗口被使用来查看和编辑项目(item)的属性。你提供对话框模板去建立每一页,就像对话框程序一样。它管理控制及设置相应项目(item)的属性。
当这页(page)获得或失去焦点时及当单击了确定(OK),取消(Cancel),应用(Apply Now)或帮助(Help)按钮时,属性表为这页发送通知消息到对话框过程。这个通知以 WM_NOTIFY 消息的形式发送。 lParam 参数是 NMHDR 结构的地址,包含了指向属性表对话框的窗口的句柄。
一些通知消息需要一个页(page)去返回TRUE或FALSE两者之一来响应 WM_NOTIFY 消息。要这么干,这个页(page)必须使用
SetWindowLong 函数去为页对话框设置DWL_MSGRESULT值为TURE或FALSE之一。
页(Pages )
一个属性表必须至少包含一个页(page),但它包含的页不能超过MAXPROPPAGES定义的值(定义在Win32头文件中)。每一页都有一个以0为开始的索引,这是属性表以添加的先后顺序分配的。这些索引被消息使用,发送到属性页。
一个属性页可以包含一个嵌套的对话框。如果这样做了,你必须为顶层对话框(top-level dialog box)包含WS_EX_CONTROLPARENT风格,并调用带有父对话框句柄的
IsDialogMessage 函数。这确保了用户在嵌套对话框中可以使用记忆术和对话框导航键去移动焦点到控件
每一个页都有一个相应的图标(icon)和标签(label)。属性表为每一页建立了一个标签卡(tab),在这个标签卡(tab)中显示图标和标签(label)。所有属性表页被期望使用非粗体字体。要确保字体不是粗体,在对话框模板中指定DS_3DLOOK风格。
不要为每一页的对话框过程调用
EndDialog 函数。这样做了将消毁整个属性表,不单单是这一页。
最小的属性页是212对话单位宽114对话单位高。如果一个页对话框比这小,那么这个页将被放大到最小属性页的大小。Prsht.h头文件包含了属性表页的默认的三个设置。PROP_SM_CXDLG和PROP_SM_CYDLG定义了被推荐的最小属性表页的尺寸。PROP_MED_CXDLG和PROP_MED_CYDLG定义了被推荐的中等大小属性表面页的尺寸。PROP_LG_CXDLG和PROP_LG_CYDLG定义了被推荐的最大属性表页的尺寸。Prsht.h也包含了属性表向导页的推荐尺寸。这些尺寸的说明参见 Wizard Property Sheets 。使用这些推荐尺寸将帮助你可视的连接你的应用程序和其它的微软Windows应用程序。
使用下列的值去设置你的属性表页的基础大小:
PROP_SM_CXDLG
小型属性表页的宽,对话单位
PROP_SM_CYDLG
小型属性表页的高,对话单位
PROP_MED_CXDLG
中型属性表页的宽,对话单位
PROP_MED_CYDLG
中型属性表页的高,对话单位
PROP_LG_CXDLG
大型属性表页的宽,对话单位
PROP_LG_CYDLG
大型属性表页的高,对话单位
属性表创造
在创造一个属性表前,你必须定义一个或多个页(pages)。这包含填充一个 PROPSHEETPAGE 结构(使用页图标,标签(label),对话框模板,对话框过程等相关信息填充),此结构用于调用 CreatePropertySheetPage 函数。这个函数返回指向HPROPSHEETPAGE类型的句柄,这是这页唯一的标识符。
要新建一个属性表,你在调用 PropertySheet 函数中指定一个 PROPSHEETHEADER 结构的地址。这个函数为属性表定义了图标和标题(title),也包含了HPROPSHEETPAGE句柄数组的地址。当 PropertySheet 新建属性表时,它包含了页在数组中的识别。这页在属性表中以在数组中包含的次序来显示。
另外新建一个属性表的途径是指定一个 PROPSHEETPAGE 结构的数组来代替HPROPSHEETPAGE句柄的数组。既然这样, PropertySheet 在添加页到属性表前为它们创造句柄。
当一个页(page)被建立时,对话框过程为页(page)接收一个WM_INITDIALOG消息。这个消息的 lParam 参数是被新建页的 PROPSHEETPAGE 结构的地址。对话框可以在结构或保存这些信息,在稍后使用它来修改这个页。
PropertySheet 自动设置属性表的大小和初始位置。当属性表被新建时,这个位置基于所有者窗口的位置,这个大小基于页的数组指定的大小。如果你想让页与属性表底部的四个按钮的宽相匹配,设置页宽为190对话单位。
添加和移去页
新建一个属性表后,一个应用程序可以使用 PSM_ADDPAGE 消息添加一个页。注意属性表的大小在它被建立后不能改变,因此新的页必须比属性表中当前的页要小。
一个应用程序使用 PSM_REMOVEPAGE 消息去移去一个页。当你定义了一个页,你可以指定一个 PropSheetPageProc 回调函数的地址来让属性表(当它正在新建或移去这个页时)调用。使用 PropSheetPageProc 给你一个机会去执行初始化和消除个别页的操作。
当一个属性表被消毁时,它自动消毁已经添加的所有页。从建立页时指定使用的数组中倒序取出页进行消毁。 要消毁一个通过 CreatePropertySheetPage 函数新建的但没有添加到属性表中的页,使用 DestroyPropertySheetPage 函数。
属性表标题 (Title)和页标签(Labels )
你在 PROPSHEETHEADER 结构中指定一个属性表的标题(title)去新建属性表。如果 dwFlags 成员包含PSH_PROPTITLE值,属性表添加“Properties for”的前缀到指定的标题字符串。你可以在属性表新建完成后通过 PSM_SETTITLE 消息来改变这个标题。
默认,一个属性表使用在对话框模板中指定的名字字符串作为页的标签。你可以通过在 PROPSHEETPAGE 结构的 dwFlags 成员中包含PSP_USETITLE值来不考虑名字字符串。 pszTitle 成员必须包含页标签字符串的地址。
页激活
一个属性表在同一时间只拥有一个活动页。这个页是活动的在层叠页的最前边。用户通过选择它的标签卡(tab)来激活一页;一个应用程序通过使用 PSM_SETCURSEL 消息激活一个页。
属性表发送 PSN_KILLACTIVE 通知消息让页失去焦点。响应消息,确认用户对这页的改变。如果这页在失去焦点之前需要附加的用户输入,它应该使用
SetWindowLong 函数去设置这页的DWL_MSGRESULT值为真(TRUE)。同样,这页应该显示一个消息框来描述问题及提供被推荐的动作。当它同意失去焦点时,这页应该设置DWL_MSGRESULT为假(FALSE)
在这页获得焦点可视以前,属性表发送 PSN_SETACTIVE 通知消息去这页。这页应该通过初始化它的控制窗口去响应。
帮助按钮
当一个页被激活时,属性表通过检查PSP_HASHELP风格来确定是否为这页打开(enable)或禁止(disable)帮助(Help)按钮。如果这页拥有这个风格,它将支持帮助(Help)按钮。如果PSP_HASHELP风格不存在,这个按钮将是禁止的。
当用户单击了帮助(Help)按钮,激活页接收 PSN_HELP 通知消息。这页应该通过显示帮助信息来响应,代表性的做法是调用 WinHelp 函数。
确定(OK),取消(Cancel)和应用(Apply Now)按钮
确定(OK)和应用(Apply Now)按钮是类似的;都是引导属性页去验证和应用用户对属性的修改。仅仅不同的是单击了确定(OK)按钮将在改变被应用后消毁属性表。
当用户单击了确定(OK)或应用(Apply Now)按钮时,属性表发送 PSN_KILLACTIVE 通过消息到活动页,给它一个机会去验证用户的修改。如果这页决定修改是有效的,它应该调用
SetWindowLong 函数去为这页设置DWL_MSGRESULT值为假(FALSE)。既然这样,属性表发送 PSN_APPLY 通知消息到每一页,指导它们去应用新的属性到相应的项目(item)。如果这页决定用户的修改是无效的,它应该设置DWL_MSGRESULT为真(TRUE),并显示一个对话框问题信息给用户。这页的剩余物至到它在响应 PSN_KILLACTIVE 消息中设置DWL_MSGRESULT为假(FALSE)为止。一个应用程序可以使用 PSM_APPLY 消息来模拟选择了应用(Apply Now)按钮。
当一个页变成活动时,应用(Apply Now)按钮开始是无效的,标志着没有任何属性改变要去应用。当这页从它的控件中收到输入,标志着用户已经编辑了一个属性,这页应该发送 PSM_CHANGED 消息去属性表。这个消息引起属性表去激活应用(Apply Now)按钮。如果用户随后单击了应用(Apply Now)或取消(Cancel)按钮,这页应该重新初始化它的控件,并发送 PSM_UNCHANGED 消息重新禁止应用(Apply Now)按钮。
有时应用(Apply Now)按钮引起一个页变成一个属性表,并且改变是不可逆的。当这发生时,这页应该发送 PSM_CANCELTOCLOSE 消息去属性表。这个消息引起属性表改变确定(OK)按钮上的文本为“关闭(Close)”,这标志着应用的改变是不可以取消的。
有时一个页改变了系统的配置,需要Windows去重启动或在改变生效前需要重新启动。当发生这样的改变后,一个页应该发送 PSM_RESTARTWINDOWS 消息或 PSM_REBOOTSYSTEM 消息去属性表。这些消息引起属性表在消毁后, PropertySheet 函数返回ID_PSRESTARTWINDOWS或ID_PSREBOOTSYSTEM值。
当用户单击了取消按钮时,表发送 PSN_RESET 通知消息到所有的页,这标志着属性表马上就要被消毁了。一个页应该使用通知去执行消除操作。
向导属性表
你可以新建一个叫做向导( wizard )的特别类型的属性表,这由一组有次序的对话框组成,它指导用户有次序的一步一步的进行操作,这很象设置一个设置或新建一张生日。在向导属性表中,页没有标签卡(tab),并且在同一时间只有一个页是可视的。同样,一个向导属性表用上一步(Back)按钮,下一步(Next)或完成(Finish)按钮替代了确定(OK)和应用(Apply Now)按钮,取消(Cancel)按钮继续存在。要告诉属性表哪一个按钮是可用的,使用带有PSWIZB_BACK,PSWIZB_NEXT,PSWIZB_FINISH和PSWIZB_DISABLEDFINISH值的 PSM_SETWIZBUTTONS 消息。
就象标准属性表一样新建和初始化一个向导属性表,当然你必须在 PROPSHEETHEADER 结构的 dwFlags 成员中包含PSH_WIZARD值。系统忽略 pszCaption 成员;替代为,在属性表的标题栏中放置当前页的标签(label)。当用户从一个页到了下一个页时,系统更新使用当前页的标签更新标题。
使用下列的值去设置你的向导属性表的基础大小。使用这些值确保你的页符合Windows的标准。
WIZ_BODYCX
在向导属性表中页主体的宽。主体不包含位图范围。
WIZ_BODYX
在向导属性表中主体的左上角的水平坐标。为页主体的升起坐标使用0
WIZ_CXBMP
在向导属性表中位图范围的宽。使用WIZ_CYDLG设置位图范围的高。
WIZ_CXDLG
在向导属性表中页的宽。
WIZ_CYDLG
在向导属性表中面的高。
对话框过程为向导属性表中的页接收所有相同的通知消息,象标准的属性表页一样。另外,一人向导属性表页接收三个标准属性表不接收物通知消息: PSN_WIZBACK , PSN_WIZNEXT 和 PSN_WIZFINISH 。当用户单击了上一步(Back),下一步(Next)或完成(Finish)按钮时,向导页接收这些通知。
当用户单击了上一步(Back)或下一步(Next)按钮时,属性表前进到先前的页或下一页。一个应用程序可以通过在 PSN_WIZBACK 或 PSN_WIZNEXT 通知中设置DWL_MSGRESULT值为-1来防止属性表提前。要立即跳到先前的页或下一页,一个应用程序应该设置DWL_MSGRESULT到被显示的对话框的标识符。
当用户单击了完成(Finish)按钮时,系统自动消毁向导属性表。一个应用程序可以通过在 PSN_WIZFINISH 通知消息中设置DWL_MSGRESULT为非零值来防止向导被消毁。
属性页扩展
一个属性页扩展是一个动态链接库,添加一个或多个页到属性表,被其它的模块建立。这个模块创造的属性页中包含一个 AddPropSheetPageProc 回调函数,这是被扩展DLL调用来添加一页。函数接收指向一个页的句柄及应用程序定义的32位值。
扩展DLL同样包含一个叫做 ExtensionPropSheetPageProc 的回调函数,接收来自这个模块的 AddPropSheetPageProc 的地址来创造属性表。扩展DLL必须输出 ExtensionPropSheetPageProc 。
Windows头文件包含了两个为属性表回调函数定义的原型。要定义 AddPropSheetPageProc ,使用下列的原型: typedef BOOL (CALLBACK FAR * LPFNADDPROPSHEETPAGE)(HPROPSHEETPAGE, LPARAM);
要定义 ExtensionPropSheetPageProc ,使用下列的原型: typedef BOOL (CALLBACK FAR * LPFNADDPROPSHEETPAGES)(LPVOID, LPFNADDPROPSHEETPAGE, LPARAM);
使用属性表
这个部分包含了怎样新建一个属性表和处理通知消息的例子。
新建一个属性表
在这部分的例子中新建了一个属性表,它包含两个页,一个是设置电子表格程序中单元的字体属性,另一个是设置单元的边框属性。例子通过填充一双 PROPSHEETPAGE 结构定义了页(pages),在 PROPSHEETHEADER 函数中指定了它的地址,并调用了 PropertySheet 函数。对话框模板,图标和页的标签(label)被从应用程序的可执行文件中的资源装入。属性表的图标也同样被从应用程序的资源中装入。 // DoPropertySheet - 新建一个包含两个页的属性表
// hwndOwner - 指向属性表的所有者窗口的句柄。
//
// 全局变量
// g_hinst - 实例句柄
extern HINSTANCE g_hinst;
VOID DoPropertySheet(HWND hwndOwner)
{
PROPSHEETPAGE psp[2];
PROPSHEETHEADER psh;
psp[0].dwSize = sizeof(PROPSHEETPAGE);
psp[0].dwFlags = PSP_USEICONID | PSP_USETITLE;
psp[0].hInstance = g_hinst;
psp[0].pszTemplate = MAKEINTRESOURCE(DLG_FONT);
psp[0].pszIcon = MAKEINTRESOURCE(IDI_FONT);
psp[0].pfnDlgProc = FontDialogProc;
psp[0].pszTitle = MAKEINTRESOURCE(IDS_FONT)
psp[0].lParam = 0;
psp[0].pfnCallback = NULL;
psp[1].dwSize = sizeof(PROPSHEETPAGE);
psp[1].dwFlags = PSP_USEICONID | PSP_USETITLE;
psp[1].hInstance = g_hinst;
psp[1].pszTemplate = MAKEINTRESOURCE(DLG_BORDER);
psp[1].pszIcon = MAKEINTRESOURCE(IDI_BORDER);
psp[1].pfnDlgProc = BorderDialogProc;
psp[1].pszTitle = MAKEINTRESOURCE(IDS_BORDER);
psp[1].lParam = 0;
psp[1].pfnCallback = NULL;
psh.dwSize = sizeof(PROPSHEETHEADER);
psh.dwFlags = PSH_USEICONID | PSH_PROPSHEETPAGE;
psh.hwndParent = hwndOwner;
psh.hInstance = g_hinst;
psh.pszIcon = MAKEINTRESOURCE(IDI_CELL_PROPERTIES);
psh.pszCaption = (LPSTR) "Cell Properties";
psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
psh.nStartPage = 0;
psh.ppsp = (LPCPROPSHEETPAGE) &psp;
psh.pfnCallback = NULL;
PropertySheet(&psh);
return;
}
处理通知消息
一个属性表发送 WM_NOTIFY 消息去从页中获取信息,并报告用户动作的页。这个消息的 lParam 参数是 NMHDR 结构的地址,这个地址包含指向属性表对话框的句柄,指向页对话框的句柄和一个通知代码。这个页必须通过设置页的DWL_MSGRESULT值为真(TRUE)或假(FALSE)来响应一些通知消息。
下列的例子是页对话框过程中的代码片段。它显示了怎样处理 PSN_HELP 通知消息 case WM_NOTIFY:
switch (((NMHDR FAR *) lParam)->code) {
case PSN_HELP:
{
char szBuf[FILE_LEN]; // buffer for name of help file
// Display help for the font properties page.
LoadString(g_hinst, IDS_HELPFILE, &szBuf, FILE_LEN)
WinHelp(((NMHDR FAR *) lParam)->hwndFrom, &szBuf,
HELP_CONTEXT, IDH_FONT_PROPERTIES);
break;
}
.
. // 在这处理其它的属性表通知
.
}
在Internet Explorer中属性表 的更新
属性表在Microsoft® Internet Explorer中支持下列的新特性。
新的通知
PSN_GETOBJECT 通知允许一个页进行OLE拖放对象。
更新的结构
PROPSHEETHEADER 和 PROPSHEETPAGE 结构已经被更新来支持新的特性。请参见这些结构的参考。