1.打开类视图,右键项目--->类向导-->添加Cpropsheet类,命名为mypropsheet
CPropertySheet
是 MFC 的一个类,用于创建包含多个属性页的对话框。它可以使用内置的向导模式,向用户显示“下一步”和“上一步”按钮
2.在Cmypropsheet.h中,声明三个属性类的对象
public:
PROP01 m_prop01;
PROP02 m_prop02;
PROP03 m_prop03;
3.在构造函数里,把三个对象加进去
Cmypropsheet::Cmypropsheet(UINT nIDCaption,
CWnd* pParentWnd, UINT iSelectPage)
:CPropertySheet(nIDCaption, pParentWnd, iSelectPage)
{
AddPage(&m_prop01);
AddPage(&m_prop02);
AddPage(&m_prop03);
}
4.在第二个构造函数里,也加进去
Cmypropsheet::Cmypropsheet(LPCTSTR pszCaption,
CWnd* pParentWnd, UINT iSelectPage)
:CPropertySheet(pszCaption, pParentWnd, iSelectPage)
{
AddPage(&m_prop01);
AddPage(&m_prop02);
AddPage(&m_prop03);
}
5.在对话框的添加按钮中,加入代码
void CrunningbuttonDlg::OnBnClickedButtonQuery()
{
Cmypropsheet dlg(__T("职业调查1111 "),this);
dlg.SetWizardMode();
dlg.DoModal();
}
第一句是通过mypropsheet构造函数创建了对象,第二个的作用是 设置为向导模式,即有了下一步,帮助,取消等按钮,第三句是创建了一个模态对话框
6.生成后,发现报错了
7.我们点击重试,看一下输出窗口,发现输出窗口提示了源码269行有错误,我们打开相应源码,定位到269行
ASSERT(::GetWindowLong(hWndCtrl, GWL_STYLE) & WS_GROUP);
这句的意思是没有设置分组,我们将按钮的组属性进行修改,将false改成true,并将m_lang修改为整型变量而不是数组,至于为什么,我也不清楚
1.在在PROP01.cpp中添加重写OnWizardNext()函数
BOOL PROP01::OnSetActive()
{
((CPropertySheet*)GetParent())->SetWizardButtons(PSWIZB_NEXT);
((CPropertySheet*)GetParent())->GetDlgItem(IDHELP)
->ShowWindow(SW_HIDE);
return CPropertyPage::OnSetActive();
}
。OnSetActive()
函数通常被视为初始化属性页的最后一个处理步骤,因此可以在这个函数中完成大部分的初始化和设置操作,例如更新属性页中的数据、设置控件的默认状态等等。
OnSetActive()
是 CPropertyPage
类的消息处理函数之一,用于处理激活属性页时发出的 PSN_SETACTIVE
通知消息
GetParent()
是一个 MFC 函数,是用于获取当前窗口的父窗口指针的,该函数的返回值是一个 CWnd*
类型的指针,指向当前窗口的父窗口。这句代码的意思是设置一个向前按钮,当前窗口的父类窗口就是指这个属性页,可是这个属性页就是这个当前的窗口,为什么还是父类呢,因为属性页才是当前窗口,而它的父类窗口就是它的对话框窗口,它们两个显示上是同一个窗口,属性页(Property Page)和对话框(Dialog)在视觉上表现为同一个窗口。这是因为属性页实际上是基于对话框窗口来实现的,也就是说属性页是以对话框形式展现的
2.在POP02.cpp中和PROP03.cpp中同样加入这些代码
判断用户是否输入数据
3.在PROP01.cpp中添加重写OnWizardNext()函数
LRESULT PROP01::OnWizardNext()
{
UpdateData();
if (m_lang==-1)
{
MessageBox(_T("请选择开发语言"),
_T("开发语言未选择"), MB_OK | MB_ICONERROR);
return -1;
}
if (m_company.GetLength()==0)
{
MessageBox(_T("请选择公司"),
_T("公司未选择"), MB_OK | MB_ICONERROR);
return -1;
}
return CPropertyPage::OnWizardNext();
}
在处理向下导航按钮的事件时阻止用户导航到下一页,则需要在 OnWizardNext()
中返回一个特定的值 -1
。
OnWizardNext()
是点击“下一步”按钮时触发的函数,它是 CPropertySheet
对象的一个成员函数
在PROP02.cpp中加入如下代码
LRESULT PROP02::OnWizardNext()
{
bool haschose = false;
UpdateData();
for (int i=0;i<4;i++)
{
if (m_skill[i] == true)
{
haschose = true;
break;
}
}
if (!haschose)
{
MessageBox(_T("技能未选择"),
_T("请选择技能"),MB_OK|MB_ICONERROR);
return -1;
}
return CPropertyPage::OnWizardNext();
}
在PROP03中加入如下代码
BOOL PROP03::OnWizardFinish()
{
UpdateData();
if (m_money.GetWindowTextLength() == 0)
{
MessageBox(_T("薪资范围未选择"),
_T("请选择薪资"), MB_OK | MB_ICONERROR);
return FALSE;
}
return CPropertyPage::OnWizardFinish();
}
注意,这里返回值是0,而不是-1,因为这个函数返回值为bool型
if (ID_WIZFINISH == dlg.DoModal())
{
CString strmsg = __T("您的选择是");
switch (dlg.m_prop01.m_lang)
{
case 0:
strmsg += __T("开发语言:C++");
break;
case 1:
strmsg += __T("开发语言:java");
break;
case 2:
strmsg += __T("开发语言:python");
break;
}
strmsg += __T("您的公司是") + dlg.m_prop01.m_company;
strmsg += __T("您的技能是");
CString strSkill[4] = { __T("网络编程")
, __T("MFC") , __T("操作系统") , __T("数据结构") };
for (int i=0;i<4;i++)
{
if (dlg.m_prop02.m_skill[i])
{
strmsg += strSkill[i] + __T(",");
}
}
strmsg += __T("您的薪资范围是") + dlg.m_prop03.text;
MessageBox(strmsg, __T("最终信息"));
}
ID_WIZFINISH
是在MFC中预定义的常量,表示“完成”按钮被点击