1. Insert-->Dialog 插入IDD_LARGER...Page....3个 Style:Child, Disable
注意:修改Page的语言属性(不是字体)必须只能在Resource View中选Dialog单独选IDD_PROP1的右键属性,而不是在资源编辑器中选择右键的属性(那里只能选择字体).
2 分别给三个属性表单页Page1,Page2,Page3 用ClassWizard创建3个类,CPage1,CPage2,CPage3
3. 属性表单页CPropertyPage实际是要附加在CPropertySheet上才能显示
(1)CPropertyPage必须加载到CPropertySheet
(2) Sheet调用DoModal去创建表单sheet,这样才能把3个page显示
4 Insert--New class 创建一个新的基于CPropertySheet的类,用来操作3个Page,这个新类叫CPropSheet
5. 向导模式 SetWizardMode
6 SetWizardButtons 解决sheet上buttons显示的问题:
要在CPage1中覆盖基类的OnSetActive() 的实现代码中解决Sheet的WizardButtons问题,为什么不直接在CPropSheet中解决?
7 在View视中定义一个CPropSheet propSheet变量,用propSheet来操作Page1,Page2,Page3
//---------CPage1类的实现
头文件Page1.h
#if !defined(AFX_PAGE1_H__2430209C_79B9_43D5_AB82_3ADD0B3D1AA8__INCLUDED_)
#define AFX_PAGE1_H__2430209C_79B9_43D5_AB82_3ADD0B3D1AA8__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// Page1.h : header file
//
/
// CPage1 dialog
class CPage1 : public CPropertyPage
{
DECLARE_DYNCREATE(CPage1)
// Construction
public:
CPage1();
~CPage1();
// Dialog Data
//{{AFX_DATA(CPage1)
enum { IDD = IDD_PROP1 };
int m_occupation;
CString m_workAddr;
//}}AFX_DATA
// Overrides
// ClassWizard generate virtual function overrides
//{{AFX_VIRTUAL(CPage1)
public:
virtual BOOL OnSetActive();
virtual LRESULT OnWizardNext();
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CPage1)
virtual BOOL OnInitDialog();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_PAGE1_H__2430209C_79B9_43D5_AB82_3ADD0B3D1AA8__INCLUDED_)
类成员实现:Page1.cpp
// Page1.cpp : implementation file
//
#include "stdafx.h"
#include "prop.h"
#include "Page1.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CPage1 property page
IMPLEMENT_DYNCREATE(CPage1, CPropertyPage)
CPage1::CPage1() : CPropertyPage(CPage1::IDD)
{
//{{AFX_DATA_INIT(CPage1)
m_occupation = -1;
m_workAddr = _T("");
//}}AFX_DATA_INIT
}
CPage1::~CPage1()
{
}
void CPage1::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CPage1)
DDX_Radio(pDX, IDC_RADIO1, m_occupation);
DDX_LBString(pDX, IDC_LIST1, m_workAddr);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CPage1, CPropertyPage)
//{{AFX_MSG_MAP(CPage1)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CPage1 message handlers
// 覆盖基类的虚函数:设置sheet上哪个WiZard button 要显示
BOOL CPage1::OnSetActive()
{
// TODO: Add your specialized code here and/or call the base class
((CPropertySheet*)GetParent())->SetWizardButtons(PSWIZB_NEXT);
return CPropertyPage::OnSetActive();
}
// 覆盖基类的虚函数:在点击"next"按钮前,获得m_occupation的值
LRESULT CPage1::OnWizardNext()
{
// TODO: Add your specialized code here and/or call the base class
UpdateData(true);
if(m_occupation==-1)
{
MessageBox("请选择你的职业");
return -1;
}
if(m_workAddr=="")
{
MessageBox("请选择你的工作地点");
return -1;
}
return CPropertyPage::OnWizardNext();
}
// 这个消息是CPage在显示之前发送的.
BOOL CPage1::OnInitDialog()
{
CPropertyPage::OnInitDialog();
// TODO: Add extra initialization here
((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
}
//------CPage2类的实现
头文件Page2.h
#if !defined(AFX_PAGE2_H__58B69281_180E_4981_A868_2AED621B7D48__INCLUDED_)
#define AFX_PAGE2_H__58B69281_180E_4981_A868_2AED621B7D48__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// Page2.h : header file
//
/
// CPage2 dialog
class CPage2 : public CPropertyPage
{
DECLARE_DYNCREATE(CPage2)
// Construction
public:
CPage2();
~CPage2();
// Dialog Data
//{{AFX_DATA(CPage2)
enum { IDD = IDD_PROP2 };
BOOL m_football;
BOOL m_basketball;
BOOL m_volleyball;
BOOL m_swim;
//}}AFX_DATA
// Overrides
// ClassWizard generate virtual function overrides
//{{AFX_VIRTUAL(CPage2)
public:
virtual BOOL OnSetActive();
virtual LRESULT OnWizardNext();
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CPage2)
// NOTE: the ClassWizard will add member functions here
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_PAGE2_H__58B69281_180E_4981_A868_2AED621B7D48__INCLUDED_)
类的实现 Page2.cpp
// Page2.cpp : implementation file
//
#include "stdafx.h"
#include "prop.h"
#include "Page2.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CPage2 property page
IMPLEMENT_DYNCREATE(CPage2, CPropertyPage)
CPage2::CPage2() : CPropertyPage(CPage2::IDD)
{
//{{AFX_DATA_INIT(CPage2)
m_football = FALSE;
m_basketball = FALSE;
m_volleyball = FALSE;
m_swim = FALSE;
//}}AFX_DATA_INIT
}
CPage2::~CPage2()
{
}
void CPage2::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CPage2)
DDX_Check(pDX, IDC_CHECK1, m_football);
DDX_Check(pDX, IDC_CHECK2, m_basketball);
DDX_Check(pDX, IDC_CHECK3, m_volleyball);
DDX_Check(pDX, IDC_CHECK4, m_swim);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CPage2, CPropertyPage)
//{{AFX_MSG_MAP(CPage2)
// NOTE: the ClassWizard will add message map macros here
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CPage2 message handlers
BOOL CPage2::OnSetActive()
{
// TODO: Add your specialized code here and/or call the base class
((CPropertySheet*)GetParent())->SetWizardButtons(PSWIZB_BACK|PSWIZB_NEXT);
return CPropertyPage::OnSetActive();
}
LRESULT CPage2::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;
}
}
//---CPage3 类的实现
头文件Page3.h
#if !defined(AFX_PAGE3_H__BFD081AC_E2AB_4685_A974_1FB0B946D8F7__INCLUDED_)
#define AFX_PAGE3_H__BFD081AC_E2AB_4685_A974_1FB0B946D8F7__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// Page3.h : header file
//
/
// CPage3 dialog
class CPage3 : public CPropertyPage
{
DECLARE_DYNCREATE(CPage3)
// Construction
public:
CString m_strSalary;
CPage3();
~CPage3();
// Dialog Data
//{{AFX_DATA(CPage3)
enum { IDD = IDD_PROP3 };
// NOTE - ClassWizard will add data members here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_DATA
// Overrides
// ClassWizard generate virtual function overrides
//{{AFX_VIRTUAL(CPage3)
public:
virtual BOOL OnSetActive();
virtual BOOL OnWizardFinish();
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CPage3)
virtual BOOL OnInitDialog();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_PAGE3_H__BFD081AC_E2AB_4685_A974_1FB0B946D8F7__INCLUDED_)
类的实现:Page3.cpp
// Page3.cpp : implementation file
//
#include "stdafx.h"
#include "prop.h"
#include "Page3.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CPage3 property page
IMPLEMENT_DYNCREATE(CPage3, CPropertyPage)
CPage3::CPage3() : CPropertyPage(CPage3::IDD)
{
//{{AFX_DATA_INIT(CPage3)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
CPage3::~CPage3()
{
}
void CPage3::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CPage3)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CPage3, CPropertyPage)
//{{AFX_MSG_MAP(CPage3)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CPage3 message handlers
BOOL CPage3::OnSetActive()
{
// TODO: Add your specialized code here and/or call the base class
((CPropertySheet*)GetParent())->SetWizardButtons(PSWIZB_BACK | PSWIZB_NEXT| PSWIZB_FINISH);
return CPropertyPage::OnSetActive();
}
BOOL CPage3::OnInitDialog()
{
CPropertyPage::OnInitDialog();
// TODO: Add extra initialization here
((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("1000元以下");
((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("1000--2000元");
((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("2000--3000元");
((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("3000元以上");
((CComboBox*)GetDlgItem(IDC_COMBO1))->SetCurSel(0); //设置默认选项 1000元以下
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
// 在点击 finish按钮时,获得用户薪资的选择
BOOL CPage3::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();
}
//------类CPropSheet : public CPropertySheet 的实现
头文件
#if !defined(AFX_PROPSHEET_H__1B859A0A_9314_4803_A031_F70427A6925A__INCLUDED_)
#define AFX_PROPSHEET_H__1B859A0A_9314_4803_A031_F70427A6925A__INCLUDED_
#include "Page2.h" // Added by ClassView
#include "Page1.h" // Added by ClassView
#include "Page3.h" // Added by ClassView
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// PropSheet.h : header file
//
/
// CPropSheet
class CPropSheet : public CPropertySheet
{
DECLARE_DYNAMIC(CPropSheet)
// Construction
public:
CPropSheet(UINT nIDCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0);
CPropSheet(LPCTSTR pszCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0);
// Attributes
public:
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CPropSheet)
//}}AFX_VIRTUAL
// Implementation
public:
CPage3 m_Page3;
CPage2 m_Page2;
CPage1 m_Page1;
virtual ~CPropSheet();
// Generated message map functions
protected:
//{{AFX_MSG(CPropSheet)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_PROPSHEET_H__1B859A0A_9314_4803_A031_F70427A6925A__INCLUDED_)
实现:
// PropSheet.cpp : implementation file
//
#include "stdafx.h"
#include "Prop.h"
#include "PropSheet.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CPropSheet
IMPLEMENT_DYNAMIC(CPropSheet, CPropertySheet)
//在2个构造函数中加载page
CPropSheet::CPropSheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)
:CPropertySheet(nIDCaption, pParentWnd, iSelectPage)
{
// 加载page
AddPage(&m_Page1);
AddPage(&m_Page2);
AddPage(&m_Page3);
// SetWizardMode(); // 这条语句的作于就是把page搞成向导模式
}
CPropSheet::CPropSheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)
:CPropertySheet(pszCaption, pParentWnd, iSelectPage)
{
// 加载page
AddPage(&m_Page1);
AddPage(&m_Page2);
AddPage(&m_Page3);
// SetWizardMode();
}
CPropSheet::~CPropSheet()
{
}
BEGIN_MESSAGE_MAP(CPropSheet, CPropertySheet)
//{{AFX_MSG_MAP(CPropSheet)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CPropSheet message handlers
在程序的View视中实现输出:
头文件CPropView.h
// PropView.h : interface of the CPropView class
//
/
#if !defined(AFX_PROPVIEW_H__F5F57441_99E9_4B4C_9F3A_E41E7646095E__INCLUDED_)
#define AFX_PROPVIEW_H__F5F57441_99E9_4B4C_9F3A_E41E7646095E__INCLUDED_
#include "Page1.h" // Added by ClassView
#include "Page2.h" // Added by ClassView
#include "Page3.h" // Added by ClassView
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CPropView : public CView
{
protected: // create from serialization only
CPropView();
DECLARE_DYNCREATE(CPropView)
// Attributes
public:
CPropDoc* GetDocument();
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CPropView)
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CPropView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
//{{AFX_MSG(CPropView)
afx_msg void OnPropertysheet();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
int m_iOccupation;
CString m_strWorkAddr;
BOOL bLike[4];
CString m_strSalary;
};
#ifndef _DEBUG // debug version in PropView.cpp
inline CPropDoc* CPropView::GetDocument()
{ return (CPropDoc*)m_pDocument; }
#endif
/
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_PROPVIEW_H__F5F57441_99E9_4B4C_9F3A_E41E7646095E__INCLUDED_)
实现:
// PropView.cpp : implementation of the CPropView class
//
#include "stdafx.h"
#include "Prop.h"
#include "PropDoc.h"
#include "PropView.h"
#include "PropSheet.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CPropView
IMPLEMENT_DYNCREATE(CPropView, CView)
BEGIN_MESSAGE_MAP(CPropView, CView)
//{{AFX_MSG_MAP(CPropView)
ON_COMMAND(IDM_PROPERTYSHEET, OnPropertysheet)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CPropView construction/destruction
CPropView::CPropView()
{
// TODO: add construction code here
m_iOccupation=-1;
m_strWorkAddr="";
memset(bLike,0,sizeof(bLike));
m_strSalary="";
}
CPropView::~CPropView()
{
}
BOOL CPropView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/
// CPropView drawing
void CPropView::OnDraw(CDC* pDC)
{
CPropDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CFont font;
font.CreatePointFont(300,"华文楷体");
CFont *pOldPen;
pOldPen = pDC->SelectObject(&font);
CString strTemp;
strTemp = "你的职业: ";
switch(m_iOccupation)
{
case 0: strTemp+="程序员";
break;
case 1: strTemp+="系统工程师";
break;
case 2: strTemp+="项目经理";
break;
default:break;
}
pDC->TextOut(0,0,strTemp);
strTemp ="你的工作地点: ";
strTemp +=m_strWorkAddr;
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
pDC->TextOut(0,tm.tmHeight,strTemp);
strTemp = "你的兴趣爱好: ";
if(bLike[0])strTemp +="足球";
if(bLike[1])strTemp +="篮球";
if(bLike[2])strTemp +="排球";
if(bLike[3])strTemp +="游泳";
pDC->TextOut(0,tm.tmHeight*2,strTemp);
strTemp = "你的薪资水平: ";
strTemp +=m_strSalary;
pDC->TextOut(0,tm.tmHeight*3,strTemp);
pDC->SelectObject(pOldPen);
}
/
// CPropView diagnostics
#ifdef _DEBUG
void CPropView::AssertValid() const
{
CView::AssertValid();
}
void CPropView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CPropDoc* CPropView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CPropDoc)));
return (CPropDoc*)m_pDocument;
}
#endif //_DEBUG
/
// CPropView message handlers
void CPropView::OnPropertysheet()
{
// TODO: Add your command handler code here
CPropSheet propSheet("微信属性表单程序"); //创建一个CPropSheet对象
// 表单要显示,还必须调用domodal或者create
propSheet.SetWizardMode(); //设置成向导模式
//创建一个模态的对话框
if(ID_WIZFINISH ==propSheet.DoModal())
{
m_iOccupation = propSheet.m_Page1.m_occupation;
m_strWorkAddr = propSheet.m_Page1.m_workAddr;
bLike[0]= propSheet.m_Page2.m_football;
bLike[1]= propSheet.m_Page2.m_basketball;
bLike[2]= propSheet.m_Page2.m_volleyball;
bLike[3]= propSheet.m_Page2.m_swim;
m_strSalary = propSheet.m_Page3.m_strSalary;
Invalidate();
}
}
//---
//---
//---
总体感觉VC做这种向导属性表单非常繁琐....远不如Delphi的结构清晰.