软件环境:visual studio 2008
先看效果图:
下面是具体做法:
1、建立以各基于对话框的MFC应用程序,例如Wizard,在向导的最后一步“生成的类”将对话框的类名改为CStep1Dlg,头文件、cpp文件相应的改过来(不改也可以,只是容易区分而已)。
2、建立的CStep1Dlg类是派生自CDialog的,我们需要将其改为派生自CPropertyPage。
在StepDlg.h文件中,类的定义class CStep1Dlg : public CPropertyPage要改过来,在Step1Dlg.cpp中,有个类是CAboutDlg,这个不要管,要改的是
CStep1Dlg::CStep1Dlg(CWnd* pParent /*=NULL*/) :CPropertyPage(CStep1Dlg::IDD) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } BEGIN_MESSAGE_MAP(CStep1Dlg, CPropertyPage) void CStep1Dlg::DoDataExchange(CDataExchange* pDX) { CPropertyPage::DoDataExchange(pDX); } BOOL CStep1Dlg::OnInitDialog() { CPropertyPage::OnInitDialog(); //后面的部分不改 } void CStep1Dlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // 使图标在工作区矩形中居中 int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // 绘制图标 dc.DrawIcon(x, y, m_hIcon); } else { CPropertyPage::OnPaint(); } }然后在资源视图里添加两个dialog资源,并添加类,基类选择CPropertyPage.界面设计一下。
现在一共有3个对话框资源了,分别将这三个对话框资源的属性里面的Border、Style、Title Bar设置为Thin、Child、True。Caption等随便设置。
3、给工程添加一个派生自CPropertySheet的类,取名CWizardSheet。
在WizardSheep.h文件里将三个对话框资源的头文件包含进来。
#include "Step1Dlg.h"
#include "Step2Dlg.h"
#include "Step3Dlg.h"
并添加三个成员变量:
private:
CStep1Dlg m_dlgStep1;
CStep2Dlg m_dlgStep2;
CStep3Dlg m_dlgStep3;
在WizardSheet.cpp文件里,找到构造函数(第一个参数类型为LPCTSTR的那个),添加如下代码:
CWizardSheet::CWizardSheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)
:CPropertySheet(pszCaption, pParentWnd, iSelectPage)
{
this->AddPage(&m_dlgStep1);
this->AddPage(&m_dlgStep2);
this->AddPage(&m_dlgStep3);
}
然后在项目的启动文件Wizard.cpp,添加头文件
#include "WizardSheet.h"
找到BOOL CWizardApp::InitInstance()函数,将
CStep1Dlg dlg;
m_pMainWnd = &dlg;
替换为
CWizardSheet dlg(_T("向导"));
m_pMainWnd = &dlg;
dlg.SetWizardMode();//这个不是DoModel了。
现在将程序编译运行下,可以发现基本上已经成型了。
4、现在要设置向导的按钮。
1)在CStep1Dlg.cpp文件里包含进#include "WizardSheet.h"
然后要重载virtual BOOL OnSetActive()函数。在工作区的左边点击“类视图”,点击CStep1Dlg类,右键,选择“属性”,在属性里切换到重写页面,找到OnSetActive,然后添加。
添加如下代码:
BOOL CStep1Dlg::OnSetActive()
{
// TODO: 在此添加专用代码和/或调用基类
CWizardSheet *ros = reinterpret_cast<CWizardSheet*>(GetParent());
ros->SetWizardButtons(PSWIZB_NEXT);//设置下一步按钮可用
return CPropertyPage::OnSetActive();
}
分别给CStep2Dlg、CStep3Dlg添加OnSetActive函数(别忘了include头文件),代码分别如下:
BOOL CStep2Dlg::OnSetActive()
{
// TODO: 在此添加专用代码和/或调用基类
CWizardSheet *ros = reinterpret_cast<CWizardSheet*>(GetParent());
ros->SetWizardButtons(PSWIZB_NEXT | PSWIZB_BACK);
return CPropertyPage::OnSetActive();
}
BOOL CStep3Dlg::OnSetActive()
{
// TODO: 在此添加专用代码和/或调用基类
CWizardSheet *ros = reinterpret_cast<CWizardSheet*>(GetParent());
ros->SetWizardButtons(PSWIZB_BACK );
return CPropertyPage::OnSetActive();
}
现在上一步、下一步按钮正常了。但是旁边的取消和帮助按钮挺烦人的,现在对它们进行改造。
5、在CWizardSheet的OnInitDialog()函数里添加如下代码:
BOOL CWizardSheet::OnInitDialog()
{
BOOL bResult = CPropertySheet::OnInitDialog();
// TODO: 在此添加您的专用代码
CButton *btnFinish;
btnFinish = reinterpret_cast<CButton *>(GetDlgItem(IDCANCEL));
btnFinish->SetWindowText(_T("完成"));
CButton *btnClose;
btnClose = reinterpret_cast<CButton *>(GetDlgItem(IDHELP));
btnClose->SetWindowText(L"关闭");
return bResult;
}
现在只是给它们化了下妆而已。接下来就要进行改头换面了。
对IDCANCEL和IDHELP消息映射函数进行改写。方法有点笨,没有找到向导添加消息映射,只好手动了。
首先在CWizardSheet.h文件里声明两个虚函数。
protected:
virtual void OnFinishButton();
virtual void OnCloseButton();
然后设置消息映射,打开WizardSheet.cpp文件,找到
BEGIN_MESSAGE_MAP(CWizardSheet, CPropertySheet)
END_MESSAGE_MAP()
在之间添加
BEGIN_MESSAGE_MAP(CWizardSheet, CPropertySheet)
ON_COMMAND(IDCANCEL, &CWizardSheet::OnFinishButton)
ON_COMMAND(IDHELP, &CWizardSheet::OnCloseButton)
END_MESSAGE_MAP()
最后是编写响应函数部分了。
void CWizardSheet::OnFinishButton()
{
AfxMessageBox(_T("The Finish button of the wizard was clicked."));
}
void CWizardSheet::OnCloseButton()
{
AfxMessageBox(_T("The wizard will be closed!"));
PostQuitMessage(0);
}
好像到这里该结束了……