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()--單擊屬性頁【完成】按鈕時程序調用該虛函數
