1、分类
标签式和向导式
2、相关类
CPropertyPage -属性页,其实就是一个对话框页面,父类是CDialog类
CPropertySheet -属性表单,父类是CWnd类
一个完整的属性页对话框由一个属性表单+多个属性页组成
属性页资源与普通对话框资源的区别:
属性页:
对话框:
3、标签式属性页
3.1插入属性页对话框资源,修改语言和字体,双击资源,生成相应的类,注意父类选择CPropertyPage类。
创建一个单文档视图的MFC工程:Prop
插入3个属性页:
注意:①这里插入的3个属性页资源的语言均为“English(U.S.)”,须右击资源修改属性为中文语言
②3个属性页Page1、Page2、Page3的字体默认均为“MS Sans Serif”,点击“字体[O]...”按键修改字体为中文字体
利用MFC类向导生成相应的属性页类:
3.2类视图下右击工程,选择添加新的类,父类是CPropertySheet类。
3.3在属性表单中添加属性页对象,在属性表单类的构造函数中调用 CPropertySheet::AddPage
首先在在属性表单对象CPropSheet的头文件PropSheet.h中分别把先前创建的三个属性页的头文件包含进来:
#include "Prop1.h"
#include "Prop2.h"
#include "Prop3.h"
然后在属性表单对象CPropSheet的头文件PropSheet.h中为三个属性页分别定义成员变量:
public:
CProp1 m_prop1;
CProp2 m_prop2;
CProp3 m_prop3;
属性表单类有两个构造函数,在构造属性表单对象时,可任选其一构造函数,调用AddPage函数添加属性页对象:
CPropSheet::CPropSheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage) :CPropertySheet(nIDCaption, pParentWnd, iSelectPage) { AddPage(&m_prop1); AddPage(&m_prop2); AddPage(&m_prop3); } CPropSheet::CPropSheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage) :CPropertySheet(pszCaption, pParentWnd, iSelectPage) { AddPage(&m_prop1); AddPage(&m_prop2); AddPage(&m_prop3); }
3.4创建显示属性表单 CPropertySheet::Domodal()
在Prop程序的主菜单上添加一个菜单项,用户单击这个菜单项后,程序显示属性表单;
在视图类中添加该菜单项的消息响应函数
在CPropView类的源文件开始部分包含CPropSheet类的头文件:
#include "stdafx.h"
#include "Prop.h"
#include "PropDoc.h"
#include "PropView.h"
#include "PropSheet.h"
在程序新添加的菜单项的响应函数中,调用DoModal函数显示一个模式化的属性表单:
void CPropView::OnPropertysheet() { // TODO: Add your command handler code here CPropSheet propSheet("属性表单"); propSheet.DoModal(); }
构造的CPropSheet类型的属性表对象propSheet调用的是以标题为参数的属性表单构造函数;
3.5当控件的值发生改变时,将应用按钮设置为可用 CPropertyPage::SetModified(TRUE);
3.6消息处理(通过在页面类中添加虚函数的方式实现)
CPropertyPage::OnApply
CPropertyPage::OnOK
CPropertyPage::OnCancel
4、向导式属性页
4.1插入属性页对话框资源,修改语言和字体,双击资源,生成相应的类,注意父类选择CPropertyPage类。
4.2类视图下右击工程,选择添加新的类,父类是CPropertySheet类。
4.3在表单类中添加属性页对象,在构造函数中调用 CPropertySheet::AddPage
---------------------------------之前的步骤与标签式属性页中创建属性表单的实现步骤一致
4.4创建和显示前,设置为向导模式 CPropertySheet::SetWizardMode
void CPropView::OnPropertysheet() { // TODO: Add your command handler code here CPropSheet propSheet("属性表单"); propSheet.SetWizardMode(); propSheet.DoModal(); }
4.5创建和显示 CPropertySheet::DoModal()
4.6设置每个页面的向导按钮
1--在 CPropertyPage::OnSetActive() 函数中设置
2--在属性页中获取表单对象的指针 GetParent()
3--设置向导按钮 CPropertySheet::SetWizardButtons()
void SetWizardButtons( DWORD dwFlags );
dwFlags:PSWIZB_BACK / PSWIZB_NEXT / PSWIZB_FINISH / PSWIZB_DISABLEDFINISH
首先在第一个属性页的类CProp1中右击添加虚函数OnSetActive,第一个属性页应该只有【下一步】和【取消】
BOOL CProp1::OnSetActive() { // TODO: Add your specialized code here and/or call the base class ((CPropertySheet*)GetParent())->SetWizardButtons(PSWIZB_NEXT); return CPropertyPage::OnSetActive(); }
为第二个属性页CProp2添加OnSetActive虚函数,第二个属性页应该有【上一步】【下一步】和【取消】
BOOL CProp2::OnSetActive() { // TODO: Add your specialized code here and/or call the base class ((CPropertySheet*)GetParent())->SetWizardButtons(PSWIZB_BACK|PSWIZB_NEXT); return CPropertyPage::OnSetActive(); }
再为第三个属性页CProp3添加OnSetActive函数,第三个属性页应该有【上一步】和【完成】
BOOL CProp3::OnSetActive() { // TODO: Add your specialized code here and/or call the base class ((CPropertySheet*)GetParent())->SetWizardButtons(PSWIZB_BACK|PSWIZB_FINISH); return CPropertyPage::OnSetActive(); }
在资源窗口的第一个属性页资源上,为单选按钮组关联一个成员变量
注意:单选按钮组的第一个单选按钮的属性中的“组”要勾选,以标识这几个单选按钮为一组,只能选择其一;
利用MFC类向导添加成员变量:
默认会在CProp1类的构造函数中将m_occupation变量初始化为-1
在选中单选按钮组的第一个单选按钮时,关联的成员变量m_occupation的值变为0;选中第二个单选按钮变为1;选中第三个单选按钮变为2;
为CProp1类添加OnWizardNext虚函数,完成对属性页上【下一步】按钮的命令响应:
LRESULT CProp1::OnWizardNext() { // TODO: Add your specialized code here and/or call the base class //须调用UpdateData函数以调用DoDataExchange来完成控件与成员变量的数据交换 UpdateData(TRUE); if(m_occupation==-1){ MessageBox("请选择你的职业"); return -1; } return CPropertyPage::OnWizardNext(); }
要在属性页显示前向列表框中添加显示内容,为CProp1类添加WM_INITDIALOG消息的响应函数OnInitDialog;列表框控件有个相应的MFC类:CListBox,利用其成员函数AddString可向列表框添加字符:
BOOL CProp1::OnInitDialog() { CPropertyPage::OnInitDialog(); // TODO: Add extra initialization here ((CListBox*)GetDlgItem(IDC_LIST1))->AddString("北京"); ((CListBox*)GetDlgItem(IDC_LIST1))->AddString("上海"); ((CListBox*)GetDlgItem(IDC_LIST1))->AddString("广州"); ((CListBox*)GetDlgItem(IDC_LIST1))->AddString("深圳"); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE }
利用MFC类向导给列表框控件关联一个成员变量m_workAddr:
LRESULT CProp1::OnWizardNext() { // TODO: Add your specialized code here and/or call the base class //调用UpdateData函数以调用DoDataExchange来完成控件与成员变量的数据交换 UpdateData(TRUE); if(m_occupation==-1){ MessageBox("请选择你的职业"); return -1; } if(m_workAddr==""){ MessageBox("请选择你的工作地点"); return -1; } return CPropertyPage::OnWizardNext(); }
在资源窗口的第二个属性页资源上,为四个复选框分别关联成员变量
程序自动将复选框控件关联的各个成员变量初始化,当复选框控件被选中时,所关联的成员变量的值为TRUE,否则为FALSE;
为CProp2类添加OnWizardNext虚函数,以在点击【下一步】时检查用户是否点选复选框
LRESULT CProp2::OnWizardNext() { // TODO: Add your specialized code here and/or call the base class UpdateData(TRUE); if(m_football || m_basketball || m_volleyball || m_swim){ return CPropertyPage::OnWizardNext(); }else{ MessageBox("请选择你的兴趣爱好"); return -1; } }
为第三个属性页的CProp3类添加WM_INITDIALOG消息的响应函数OnInitDialog;组合框对应的MFC类为CComboBox,利用该类的成员函数AddString向组合框控件的列表框中添加选项;
BOOL CProp3::OnInitDialog() { CPropertyPage::OnInitDialog(); // TODO: Add extra initialization here ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("10000元以下"); ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("10000-20000元"); ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("20000-30000元"); ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("30000元以上"); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE }
要是组合框的下拉选项的顺序和添加的顺序一样,须勾选掉资源窗口中组合框资源的属性中样式里的“分类”:
要使得组合框中在显示时有一个默认的选中项,须使用SetCurSel函数实现:
int SetCurSel(int nSelect);
参数为选项的位置索引;如果为-1,则将移除组合框的当前选项并清空编辑框中的内容;
BOOL CProp3::OnInitDialog() { CPropertyPage::OnInitDialog(); // TODO: Add extra initialization here ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("10000元以下"); ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("10000-20000元"); ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("20000-30000元"); ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("30000元以上"); ((CComboBox*)GetDlgItem(IDC_COMBO1))->SetCurSel(0); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE }
为第三个属性页CProp3类添加成员变量:CString m_strSalary,用来接收用户的选择;给CProp3类添加虚函数:OnWizardFinish,用来处理【完成】按钮的单击消息;
为了获取用户在第三个属性页CProp3中的组合框的选择项,须先利用GetCurSel函数获得组合框中当前选项的位置,再利用GetLBText函数获得组合框的相应位置的对应字符串;
BOOL CProp3::OnWizardFinish() { // TODO: Add your specialized code here and/or call the base class int index; index=((CComboBox*)GetDlgItem(IDC_COMBO1))->GetCurSel(); ((CComboBox*)GetDlgItem(IDC_COMBO1))->GetLBText(index,m_strSalary); return CPropertyPage::OnWizardFinish(); }
为了接收用户在向导类属性列表的各个属性页中的选择,在程序的视图类中须定义相应的成员变量来保存;
然后在视图类的构造函数中初始化这些成员变量:
CPropView::CPropView() { // TODO: add construction code here m_iOccupation=-1; m_strWorkAddr=""; memset(m_bLike,0,sizeof(m_bLike)); //对数组m_bLike进行快速初始化 m_strSalary=""; }
判断只有当用户点击的是【完成】按钮,程序才接收各个属性页中的选择项:
void CPropView::OnPropertysheet() { // TODO: Add your command handler code here CPropSheet propSheet("属性表单"); propSheet.SetWizardMode(); if(ID_WIZFINISH==propSheet.DoModal()){ m_iOccupation=propSheet.m_prop1.m_occupation; m_strWorkAddr=propSheet.m_prop1.m_workAddr; m_bLike[0]=propSheet.m_prop2.m_football; m_bLike[1]=propSheet.m_prop2.m_basketball; m_bLike[2]=propSheet.m_prop2.m_volleyball; m_bLike[3]=propSheet.m_prop2.m_swim; m_strSalary=propSheet.m_prop3.m_strSalary; Invalidate(); } }
4.7消息处理函数
虚函数:
OnSetActive()--当属性页被选中时,使其成为当前的活动页面
OnCancel()--单击属性页的【取消】按钮时程序调用该虚函数
OnWizardNext()--单击属性页上【下一步】按钮时程序调用该虚函数;如果返回0,则自动进入当前向导的下一个属性页;如果返回-1,属性页不发生变化;
OnWizardBack()--单击属性页【上一步】按钮时程序调用该虚函数
OnWizardFinish()--单击属性页【完成】按钮时程序调用该虚函数