创建一个属性表
关于这些类的解释就全部讲完了,现在需要一个例子程序演示如何使用它们。本章的例子工程是一个简单的SDI程序,它在客户区显示一幅图片并使用一总颜色填充背景,使用的图片和颜色可以通过一个选项对话框(一个属性表)来设置,还有一个向导(稍后会介绍)。
最简单的属性表
首先用WTL的向导创建一个SDI工程,然后为关于对话框添加一个属性表。首先改变向导创建的关于对话框样式,使它用起来像个属性页。
第一步就是去除OK按钮,因为属性表不希望属性页自己关闭。在Style Tab中,将对话框样式改为Child,Thin Border,选择Title Bar,在More Styles tab,选择Disabled。
第二步(也是最后一步)是在OnAppAbout()的处理函数中创建一个属性表,我们使用非定制的CPropertySheet 和 CPropertyPage类:
LRESULT CMainFrame::OnAppAbout(...) { CPropertySheet sheet ( _T("About PSheets") ); CPropertyPage<IDD_ABOUTBOX> pgAbout;
sheet.AddPage ( pgAbout ); sheet.DoModal(); return 0; } |
结果看起来向下面这样:
创建一个有用的属性页
并不是每一个属性表中的每一个属性页都像关于对话框这么简单,大多数属性页需要使用CPropertyPageImpl的派生类,所以我们现在就看一个这样的类。我们创建了一个新的属性页用来设置客户区背景显示的图片,它是这个样子的:
这个对话框的样式和关于页面相同,我们需要一个新类来和这个属性页协同工作,我们将其命名为CBackgroundOptsPage。这个类是从CPropertyPageImpl类派生的,它有一个CWinDataExchange来支持DDX。
class CBackgroundOptsPage : public CPropertyPageImpl<CBackgroundOptsPage>, public CWinDataExchange<CBackgroundOptsPage> { public: enum { IDD = IDD_BACKGROUND_OPTS };
// Construction CBackgroundOptsPage(); ~CBackgroundOptsPage();
// Maps BEGIN_MSG_MAP(CBackgroundOptsPage) MSG_WM_INITDIALOG(OnInitDialog) CHAIN_MSG_MAP(CPropertyPageImpl<CBackgroundOptsPage>) END_MSG_MAP()
BEGIN_DDX_MAP(CBackgroundOptsPage) DDX_RADIO(IDC_BLUE, m_nColor) DDX_RADIO(IDC_ALYSON, m_nPicture) END_DDX_MAP()
// Message handlers BOOL OnInitDialog ( HWND hwndFocus, LPARAM lParam );
// Property page notification handlers int OnApply();
// DDX variables int m_nColor, m_nPicture; }; |
关于这个类需要注意几点:
有一个名为IDD的公有成员将对话框于资源联系起来。
消息映射链和CDialogImpl相似。
消息映射链将消息链入CPropertyPageImpl,从而使我们能够处理与属性表相关的通知消息。
有一个OnApply()处理函数在单击属性表中的OK按钮时保存用户的选择。
OnApply() 非常简单,它调用 DoDataExchange() 更新 DDX 变量,然后返回一个代码标识是否可以关闭这个属性表:
int CBackgroundOptsPage::OnApply() { return DoDataExchange(true) PSNRET_NOERROR : PSNRET_INVALID; } |
我们还要在主窗口添加一个Tools|Options菜单来打开属性表,这个菜单的处理函数创建一个属性表,但是添加了一个新属性页CBackgroundOptsPage。
void CMainFrame::OnOptions ( UINT uCode, int nID, HWND hwndCtrl ) { CPropertySheet sheet ( _T("PSheets Options"), 0 ); CBackgroundOptsPage pgBackground; CPropertyPage<IDD_ABOUTBOX> pgAbout;
pgBackground.m_nColor = m_view.m_nColor; pgBackground.m_nPicture = m_view.m_nPicture;
sheet.m_psh.dwFlags |= PSH_NOAPPLYNOW;
sheet.AddPage ( pgBackground ); sheet.AddPage ( pgAbout );
if ( IDOK == sheet.DoModal() ) m_view.SetBackgroundOptions ( pgBackground.m_nColor,pgBackground.m_nPicture ); } |
属性表的构造函数的第二个参数是0,表示将索引是0的页面初始是可见的,你可以将其设为1,使得属性表第一次显示时显示关于页面。既然是演示代码,我就偷个懒,使用一个公有变量与CBackgroundOptsPage属性页的radio button建立关联,在主窗口中直接为其赋初始值,当用户单击属性表的OK按钮时在将其读出来。
如果用户点击OK按钮,DoModal()发挥IDOK,我们通知视图窗口使用新的图片和背景颜色。下面是几个屏幕截图显示几个不同的样式的视图:
|