在MSDN中详细介绍了CPropertySheet、CPropertyPage的使用方法,这里概要介绍主要步骤,是为笔记。
概述
一个CPropertySheet对象会包括一个或多个CPropertyPage对象,当操作界面复杂的时候,可以按照逻辑把这些操作分解到一个或多个CPropertyPage中。
MSDN中的PropertySheets使用方法是从MSDN中摘录出来的有关详细介绍使用步骤的文档,尽管如此,内容还是有点多。作为备忘的性质,本文以一个简单的例子来进一步浓缩使用步骤。——第一次了解这一块的内容,则还是需要详细阅读MSDN的文档。
这个例子是以一个简单的加法和减法为例,效果:
在主界面上单击按钮的时候,弹出来一个property sheet,其中包括2个page,分别是加法和减法运算。“确定”之后,会把两个页面的运算内容更新到主界面的只读文本框中。
主界面这个文本框的目的仅在于说明调用者可以获取property sheet的数据。
Step 1: 创建property page对应的对话框资源
具体到本例,就是创建加法运算的对话框资源和减法运算的对话框资源。
定义如下:
IDD_ADDITION DIALOGEX 0, 0, 178, 144
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION | WS_SYSMENU
CAPTION "Addition"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
EDITTEXT IDC_X,50,23,92,19,ES_AUTOHSCROLL
LTEXT "x",IDC_STATIC,30,26,13,18
EDITTEXT IDC_Y,50,50,92,19,ES_AUTOHSCROLL
LTEXT "y",IDC_STATIC,30,53,13,18
EDITTEXT IDC_RESULT,50,76,92,19,ES_AUTOHSCROLL | WS_DISABLED
LTEXT "x+y",IDC_STATIC,30,79,13,18
PUSHBUTTON "Add",IDC_ADD,30,110,111,17
END
IDD_SUBTRACTION DIALOGEX 0, 0, 183, 148
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION | WS_SYSMENU
CAPTION "Subtraction"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
EDITTEXT IDC_X,50,23,92,19,ES_AUTOHSCROLL
LTEXT "x",IDC_STATIC,30,26,13,18
EDITTEXT IDC_Y,50,50,92,19,ES_AUTOHSCROLL
LTEXT "y",IDC_STATIC,30,53,13,18
EDITTEXT IDC_RESULT,50,76,92,19,ES_AUTOHSCROLL | WS_DISABLED
LTEXT "x+y",IDC_STATIC,30,79,13,18
PUSHBUTTON "Subtract",IDC_SUBTRACT,30,110,111,17
END
要点:
- 要把VS自动添加的OK和Cancel都删除掉;——因为CPropertySheet对象DoModal()的时候会自动添加这些按钮。
- Caption:设置成page对应的tab标签要显示的文本。
- Style:选择Child
- Border:选择Thin
- Titlebar:选择True(某些版本的VS是Checkbox类型,勾选即可)
- Disabled:True
Step 2: 为property page映射成对话框类,并添加相关代码
通过ClassWizard为两个对话框资源创建对应的class,此时选择CPropertyPage作为基类。代码拷贝如下。
要点
- 选择CPropertyPage作为基类
- 重载虚函数OnOK()
CAdditionPage
头文件
#pragma once
#include "resource.h"
// CAddition 对话框
class CAdditionPage : public CPropertyPage
{
DECLARE_DYNAMIC(CAdditionPage)
public:
CAdditionPage();
virtual ~CAdditionPage();
int GetX() const;
int GetY() const;
int GetResult() const;
// 对话框数据
enum { IDD = IDD_ADDITION };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
DECLARE_MESSAGE_MAP()
private:
int m_x;
int m_y;
int m_result;
public:
afx_msg void OnBnClickedAdd();
virtual void OnOK();
};
实现文件
#include "stdafx.h"
#include "PropertySheetEx.h"
#include "AdditionPage.h"
#include "afxdialogex.h"
// CAddition 对话框
IMPLEMENT_DYNAMIC(CAdditionPage, CPropertyPage)
CAdditionPage::CAdditionPage()
: CPropertyPage(CAdditionPage::IDD)
, m_x(0)
, m_y(0)
, m_result(0)
{
}
CAdditionPage::~CAdditionPage()
{
}
void CAdditionPage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
DDX_Text(pDX, IDC_X, m_x);
DDX_Text(pDX, IDC_Y, m_y);
DDX_Text(pDX, IDC_RESULT, m_result);
}
BEGIN_MESSAGE_MAP(CAdditionPage, CPropertyPage)
ON_BN_CLICKED(IDC_ADD, &CAdditionPage::OnBnClickedAdd)
END_MESSAGE_MAP()
// CAddition 消息处理程序
void CAdditionPage::OnBnClickedAdd()
{
UpdateData(TRUE);
m_result = m_x + m_y;
UpdateData(FALSE);
}
int CAdditionPage::GetX() const
{
return m_x;
}
int CAdditionPage::GetY() const
{
return m_y;
}
int CAdditionPage::GetResult() const
{
return m_result;
}
void CAdditionPage::OnOK()
{
UpdateData(TRUE);
m_result = m_x + m_y;
//Can be deleted.
UpdateData(FALSE);
CPropertyPage::OnOK();
}
CSubtractionPage
头文件
#pragma once
// CSubtractionPage 对话框
class CSubtractionPage : public CPropertyPage
{
DECLARE_DYNAMIC(CSubtractionPage)
public:
CSubtractionPage();
virtual ~CSubtractionPage();
int GetX() const;
int GetY() const;
int GetResult() const;
// 对话框数据
enum { IDD = IDD_SUBTRACTION };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedSubtract();
private:
int m_x;
int m_y;
int m_result;
public:
virtual void OnOK();
};
实现文件
// SubtractionPage.cpp : 实现文件
//
#include "stdafx.h"
#include "PropertySheetEx.h"
#include "SubtractionPage.h"
#include "afxdialogex.h"
// CSubtractionPage 对话框
IMPLEMENT_DYNAMIC(CSubtractionPage, CPropertyPage)
CSubtractionPage::CSubtractionPage()
: CPropertyPage(CSubtractionPage::IDD)
, m_x(0)
, m_y(0)
, m_result(0)
{
}
CSubtractionPage::~CSubtractionPage()
{
}
void CSubtractionPage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
DDX_Text(pDX, IDC_X, m_x);
DDX_Text(pDX, IDC_Y, m_y);
DDX_Text(pDX, IDC_RESULT, m_result);
}
BEGIN_MESSAGE_MAP(CSubtractionPage, CPropertyPage)
ON_BN_CLICKED(IDC_SUBTRACT, &CSubtractionPage::OnBnClickedSubtract)
END_MESSAGE_MAP()
// CSubtractionPage 消息处理程序
void CSubtractionPage::OnBnClickedSubtract()
{
UpdateData(TRUE);
m_result = m_x - m_y;
UpdateData(FALSE);
}
int CSubtractionPage::GetX() const
{
return m_x;
}
int CSubtractionPage::GetY() const
{
return m_y;
}
int CSubtractionPage::GetResult() const
{
return m_result;
}
void CSubtractionPage::OnOK()
{
UpdateData(TRUE);
m_result = m_x - m_y;
// Can be deleted.
UpdateData(FALSE);
CPropertyPage::OnOK();
}
Step 3: 创建CPropertySheet子类
实际上,并不一定要创建一个CPropertySheet子类;也可以动态创建CPropertySheet对象。这方面参考MSDN即可。
本例则创建一个CPropertySheet子类,这也是比较场景的情形。
这个类:
- 以CPropertySheet为子类
- 为每个property page对象创建一个数据成员
- 在构造函数中设置sheet和各个page的属性
- 其他的数据处理等
头文件
#pragma once
#include "AdditionPage.h"
#include "SubtractionPage.h"
class CCalculator: public CPropertySheet
{
public:
CCalculator(void);
~CCalculator(void);
int GetAdditionX();
int GetAdditionY();
int GetAdditionResult();
int GetSubtractionX();
int GetSubtractionY();
int GetSubtractionResult();
private:
CAdditionPage m_additionPage;
CSubtractionPage m_subtractionPage;
};
注意到,这里加了一系列的getter,如前所述,只是为了演示如何从property sheet对象获取数据而已。通常,调用者还需要初始化property sheet对象,此时就可以设计一系列的setter。
实现文件
#include "StdAfx.h"
#include "Calculator.h"
CCalculator::CCalculator(void)
{
AddPage(&m_additionPage);
AddPage(&m_subtractionPage);
m_psh.pszCaption = _T("Calculator");
m_psh.dwFlags &= ~PSH_HASHELP;
m_psh.dwFlags |= PSH_NOAPPLYNOW;
m_additionPage.m_psp.dwFlags&= ~PSP_HASHELP;
m_subtractionPage.m_psp.dwFlags&= ~PSP_HASHELP;
}
CCalculator::~CCalculator(void)
{
}
int CCalculator::GetAdditionX()
{
return m_additionPage.GetX();
}
int CCalculator::GetAdditionY()
{
return m_additionPage.GetY();
}
int CCalculator::GetAdditionResult()
{
return m_additionPage.GetResult();
}
int CCalculator::GetSubtractionX()
{
return m_subtractionPage.GetX();
}
int CCalculator::GetSubtractionY()
{
return m_subtractionPage.GetY();
}
int CCalculator::GetSubtractionResult()
{
return m_subtractionPage.GetResult();
}
Step 4:开始尽情享用property sheet
一切已经就绪,现在就展示这个属性表。如前面的截图所示,在UI中单击按钮调出属性页,属性页OK之后显示运算信息到文本框中。
UI对话框资源
IDD_PROPERTYSHEETEX_DIALOG DIALOGEX 0, 0, 213, 94
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_APPWINDOW
CAPTION "PropertySheetEx"
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
PUSHBUTTON "Calculator",IDC_CALCULATOR,31,14,142,22
EDITTEXT IDC_INFO,34,48,142,31,ES_MULTILINE | ES_AUTOHSCROLL | WS_DISABLED
END
调用代码
void CPropertySheetExDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Text(pDX, IDC_INFO, m_info);
}
void CPropertySheetExDlg::OnBnClickedCalculator()
{
CCalculator calculator;
if (IDOK == calculator.DoModal()) {
char buffer[64];
sprintf(buffer, "%d + %d = %d\r\n%d - %d = %d",
calculator.GetAdditionX(),
calculator.GetAdditionY(),
calculator.GetAdditionResult(),
calculator.GetSubtractionX(),
calculator.GetSubtractionY(),
calculator.GetSubtractionResult());
m_info = CString(buffer);
} else {
m_info = "User cancelled.";
}
UpdateData(FALSE);
}