一个属性表包含的一个或多个层叠的窗口叫做页(pages),各自包含着一组相关属性的设置窗口。例如,一个页可以包含设置项目(item)
字体的类型风格,大小,颜色等属性的控制。每页有一个标签(tab),用户可以使用它选择页,使用它移到属性表中的最显著的位置。
一个属性表和页实际上包含在对话框中。属性表是一个系统定义的对话框,它管理页及为它们提供一个公共容器。属性表对话框可以是模式的或
非模式的。它包括一 个框架,一个标题栏和四个按钮:确定(OK),取消(Cancel),应用(Apply Now)和帮助(Help)。(帮助(Help)
按钮可能是被隐藏着的,象上面的图解)当用户单击了按钮时,对话框过程为页接收通知消息。
在CPropertySheet中有一个PROPSHEETHEADER的结构体m_psh,PROPSHEETHEADER保存了属性表的信息,如:标题,风格等等。
还有个变量CPtrArray m_pages;保存属性页的指针
CPropertySheet有两个很重要的函数:
1.void AddPage(CPropertyPage* pPage)
它的主要的作用:首先把指针加入m_pages,然后检测m_hWnd是否为空,如果不是,经过一系列的内部处理,最后调用CreateProperySheetPage
创建属性叶。
2.void BulidPropPageArray()
它的处理的过程:删除属性页数组并赋予空。然后创建新的属性页数组ppsp,大小从m_pages得知.
然后复制个m_psh的成员ppsh:m_psh.ppsh=ppsh.然后把每个属性页的m_psp(CPropertyPage中的成员)
赋给m_psh.ppsh[i].最后调用:m_psh.nPages=m_pages.GetSize();
属性表有两个方式,一是向导方式,一是正常方式。
在向导方式中:一、每一页有三种按钮,“上一步”,“下一步”,“取消”
在属性页有相应的处理函数,这三个按钮是属性表,怎会是在属性页调用呢?
其实首先相应按钮消息是属性表,然后属性表想当前的属性页发送一个WM_NOTIFY的消息,在这消息处理中得到处理。
BOOL CPropertyPage::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
ASSERT(pResult != NULL);
NMHDR* pNMHDR = (NMHDR*)lParam;
if (CDialog::OnNotify(wParam, lParam, pResult))
return TRUE;
if (pNMHDR->hwndFrom != m_hWnd && pNMHDR->hwndFrom != ::GetParent(m_hWnd))
return FALSE;
switch (pNMHDR->code)
{
case PSN_SETACTIVE:
{
CPropertySheet* pSheet = DYNAMIC_DOWNCAST(CPropertySheet, GetParent());
if (pSheet != NULL && !(pSheet->m_nFlags & WF_CONTINUEMODAL) && !(pSheet->m_bModeless))
*pResult = -1;
else
*pResult = OnSetActive() ? 0 : -1;
}
break;
case PSN_KILLACTIVE:
*pResult = !OnKillActive();
break;
case PSN_APPLY:
*pResult = OnApply() ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE;
break;
case PSN_RESET:
OnReset();
break;
case PSN_QUERYCANCEL:
*pResult = !OnQueryCancel();
break;
case PSN_WIZNEXT:
// Win32 will send a PSN_WIZBACK even if the button is disabled.
if (IsButtonEnabled(ID_WIZNEXT))
*pResult = MapWizardResult(OnWizardNext());
break;
case PSN_WIZBACK:
// Win32 will send a PSN_WIZBACK even if the button is disabled.
if (IsButtonEnabled(ID_WIZBACK))
*pResult = MapWizardResult(OnWizardBack());
break;
case PSN_WIZFINISH:
*pResult = reinterpret_cast<LRESULT>(OnWizardFinishEx());
break;
case PSN_HELP:
SendMessage(WM_COMMAND, ID_HELP);
break;
default:
return FALSE; // not handled
}
return TRUE; // handled
}
在一般模式中,选择各个页时,不是触发属性表的WM_COMMAND消息,而是属性页的WM_NOTITY.
从BOOL CPropertyPage::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)中
可以看出相应的消息如:OnApply,OnOk等等都是框架负责调用的,属性表响应。
在处理按钮”应用“时,有两个方式:
1.在属性表中处理,按钮是属性表的子控件,怎么响应是很简单,在响应函数中向需要数据的类发送自定义消息
在后每个属性页都要调用SetModified(false);
2.在属性页里重载OnApply函数。只需要一个属性页重载OnApply函数(第一页中),因为默认是第一页,但可以通过SetActivePage
来改变默认活动页。