首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

VC++ 屬性頁/精靈實作教程:CPropertySheet 與 CPropertyPage 完整流程

     編輯:關於C語言

MFC 專案中實現「屬性頁」或「精靈」介面,核心類別為 CPropertySheet (屬性表/精靈容器) 與 CPropertyPage (單頁)。本文從資源建立、類別產生、精靈模式啟用、按鈕控制、資料驗證、資料回傳到視圖顯示,提供完整實作步驟與關鍵程式碼。

1. 建立對話方塊資源

  • 資源檢視 → 新增三個 Dialog,ID 設為 IDD_PROPAGE_LARGE,分別命名 IDD_PAGE1、IDD_PAGE2、IDD_PAGE3。
  • 各頁面放置控制項:P1=Radio Button 群組+List Box;P2=Check Box 群組;P3=Combo Box。
  • **重要**:Radio Button 群組第一個勾選 **Group** 屬性,確保互斥。

2. 產生 CPropertyPage 衍生類別

  • 類別精靈 → 加入類別 → 基類 CPropertyPage,分別命名 CPage1、CPage2、CPage3。
  • 各類別使用 **Add Variable** 綁定控制項變數(CListBox、CComboBox、int 等)。

3. 產生 CPropertySheet 容器類別


// CMyPropSheet.h
class CMyPropSheet : public CPropertySheet {
    DECLARE_DYNAMIC(CMyPropSheet)
public:
    CPage1 m_page1;
    CPage2 m_page2;
    CPage3 m_page3;
    CMyPropSheet(UINT nIDCaption, CWnd* pParent = NULL, UINT iSelectPage = 0);
    CMyPropSheet(LPCTSTR pszCaption, CWnd* pParent = NULL, UINT iSelectPage = 0);
    virtual ~CMyPropSheet();
};

// CMyPropSheet.cpp
CMyPropSheet::CMyPropSheet(LPCTSTR pszCaption, CWnd* pParent, UINT iSelectPage)
    : CPropertySheet(pszCaption, pParent, iSelectPage) {
    AddPage(&m_page1);
    AddPage(&m_page2);
    AddPage(&m_page3);
    // 精靈模式:在 DoModal() 前呼叫
    // SetWizardMode();
}

4. 精靈模式與按鈕控制


// 呼叫端 (如 View 類別)
CMyPropSheet sheet(_T("設定精靈"), this);
sheet.SetWizardMode(); // 關鍵:啟用精靈模式
if (sheet.DoModal() == ID_WIZFINISH) {
    // 取得各頁資料...
}

動態控制「上一步/下一步/完成」按鈕

在各 CPageN 覆寫 OnSetActive():


BOOL CPage1::OnSetActive() {
    CPropertySheet* pSheet = (CPropertySheet*)GetParent();
    pSheet->SetWizardButtons(PSWIZB_NEXT); // 首頁只有「下一步」
    return CPropertyPage::OnSetActive();
}
BOOL CPage2::OnSetActive() {
    CPropertySheet* pSheet = (CPropertySheet*)GetParent();
    pSheet->SetWizardButtons(PSWIZB_BACK | PSWIZB_NEXT); // 中間頁
    return CPropertyPage::OnSetActive();
}
BOOL CPage3::OnSetActive() {
    CPropertySheet* pSheet = (CPropertySheet*)GetParent();
    pSheet->SetWizardButtons(PSWIZB_BACK | PSWIZB_FINISH); // 尾頁「完成」
    return CPropertyPage::OnSetActive();
}

5. 資料驗證:決定能否進入下一頁

覆寫 OnWizardNext() (按下「下一步」時) / OnWizardFinish() (按下「完成」時):**回傳 0 允許繼續,回傳 -1 取消跳轉**。


LRESULT CPage1::OnWizardNext() {
    UpdateData(TRUE); // 從控制項讀取資料到變數
    if (m_selectedJob < 0) { // 未選擇職業
        AfxMessageBox(_T("請選擇職業"));
        return -1; // 留在本頁
    }
    return 0; // 允許進入下一頁
}

LRESULT CPage3::OnWizardFinish() {
    UpdateData(TRUE);
    int idx = m_comboSalary.GetCurSel();
    if (idx == CB_ERR) { AfxMessageBox(_T("請選擇薪資")); return -1; }
    m_comboSalary.GetLBText(idx, m_strSalary);
    return 0; // 允許結束精靈
}

6. ListBox / ComboBox 初始化

在各頁 OnInitDialog() 中:


BOOL CPage1::OnInitDialog() {
    CPropertyPage::OnInitDialog();
    m_listBox.AddString(_T("項目一"));
    m_listBox.AddString(_T("項目二"));
    return TRUE;
}

7. 精靈結束後將資料回傳視圖顯示


void CMyView::OnShowWizard() {
    CMyPropSheet sheet(_T("資料輸入精靈"), this);
    sheet.SetWizardMode();
    if (sheet.DoModal() == ID_WIZFINISH) {
        m_strJob = sheet.m_page1.m_strJob;
        m_strHobby = sheet.m_page2.m_strHobby;
        m_strSalary = sheet.m_page3.m_strSalary;
        Invalidate(); // 觸發 OnDraw 重繪
    }
}
void CMyView::OnDraw(CDC* pDC) {
    pDC->TextOut(10, 10, m_strJob);
    pDC->TextOut(10, 30, m_strHobby);
    pDC->TextOut(10, 50, m_strSalary);
}

關鍵點總結

  • ✅ SetWizardMode() 必須在 DoModal() 前呼叫。
  • ✅ 按鈕控制在 OnSetActive() 中透過 GetParent() 轉型為 CPropertySheet* 呼叫 SetWizardButtons()。
  • ✅ 驗證邏輯放在 OnWizardNext()/OnWizardFinish(),回傳 -1 阻擋跳轉。
  • ✅ 控制項資料交換務必呼叫 UpdateData(TRUE/FALSE)。
  • ✅ 字體/語言亂碼問題:確保專案字元集 (Unicode/MBCS) 與資源字體一致。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved