嚮導對話框將複雜設定拆解為逐步引導,提升使用者體驗。MFC 提供 CPropertySheet + CPropertyPage 快速建構標準嚮導,但按鈕樣式、位置、圖示皆不可調。本文先示範標準嚮導,再完整實作一個完全自訂 UI 的 CustomWizard,支援任意按鈕樣式、動畫切換、自定版面。
CPropertyPage:繼承 CDialog,Style 必須為 Child、Border 為 ThinCPropertySheet:容器,DoModal() 後自動擁有「上一步/下一步/完成/取消」按鈕IDD_STEP1/2/3,對應類別 CStep1/2/3 繼承 CPropertyPageCWizard 繼承 CPropertySheet
CWizard MyWizard(_T("我的嚮導"), this, 1);
CStep1 MyStep1; CStep2 MyStep2; CStep3 MyStep3;
MyWizard.AddPage(&MyStep1);
MyWizard.AddPage(&MyStep2);
MyWizard.AddPage(&MyStep3);
MyWizard.SetWizardMode(); // 關鍵:切換為嚮導模式
MyWizard.SetActivePage(&MyStep1); // 指定第一頁
MyWizard.DoModal();
OnSetActive 控制按鈕顯示:
// 第一頁:只有下一步
pParent->SetWizardButtons(PSWIZB_NEXT);
// 中間頁:上一步 + 下一步
pParent->SetWizardButtons(PSWIZB_BACK | PSWIZB_NEXT);
// 最後頁:上一步 + 完成
pParent->SetWizardButtons(PSWIZB_BACK | PSWIZB_FINISH);
CWizard : public CDialog(資源 IDC_WIZARD)CDialog(Child、無標題、無邊框)PAGELINK 管理所有頁面rectPage
struct PAGELINK {
UINT nNum; // 頁碼
CDialog* pDialog; // 頁面對話框指標
PAGELINK* Next; // 下一頁
};
AddPage()
void CWizard::AddPage(CDialog* pDialog, UINT nID) {
PAGELINK* pNew = new PAGELINK;
pNew->pDialog = pDialog;
pNew->pDialog->Create(nID, this); // 無模式建立
pNew->pDialog->ShowWindow(SW_HIDE);
pNew->pDialog->MoveWindow(rectPage); // 定位到預設區域
// 檢查樣式:必須 WS_CHILD、無 WS_BORDER
// 插入鏈表尾端...
}
ShowPage()
void CWizard::ShowPage(UINT nPos) {
// 遍歷鏈表,顯示 nPos,隱藏其他
// 更新 nCurrentPage
// 呼叫 SetWizButton() 更新按鈕狀態
}
SetWizButton()
void CWizard::SetWizButton(UINT uFlag) {
// uFlag: 0=首頁(禁用上一步), 1=中間頁, 2=尾頁(禁用下一步,啟用完成)
GetDlgItem(IDC_PREV)->EnableWindow(uFlag != 0);
GetDlgItem(IDC_NEXT)->EnableWindow(uFlag != 2);
GetDlgItem(IDC_FINISH)->EnableWindow(uFlag == 2);
}
void CWizard::OnNext() { ShowPage(++nCurrentPage); }
void CWizard::OnPrev() { ShowPage(--nCurrentPage); }
void CWizard::OnFinish(){ AfxMessageBox(_T("採用預設值完成嚮導")); OnOK(); }
void CWizard::OnCancel(){ if (AfxMessageBox(IDS_QUIT, MB_OKCANCEL|MB_ICONQUESTION)==IDCANCEL) return; OnCancel(); }
BOOL CWizard::OnInitDialog() {
CDialog::OnInitDialog();
// 計算 rectPage:以 IDC_POS 控制項為參考區域
// 建立三個頁面並 AddPage
ShowPage(1);
return TRUE;
}
void CWizard::OnDestroy() {
// 遍歷鏈表 DestroyWindow + delete 每個頁面與節點
CDialog::OnDestroy();
}
void CCustomWizardDlg::OnBeginWiz() {
CWizard MyWiz;
MyWiz.DoModal();
}

| 特性 | 標準嚮導 | 自訂嚮導 |
|---|---|---|
| 開發速度 | 極快 | 中等 |
| 按鈕樣式/位置 | 固定 | 完全自訂 |
| 頁面切換動畫 | 無 | 可自行實作 |
| 預設完成按鈕 | 無 | 支援 |
| 適用場景 | 內部工具、快速原型 | 商業軟體、品牌化 UI |
完整原始碼請參考本文配套下載。兩種方案均在 VC6.0 + Win2000 編譯通過,亦相容新版 Visual Studio。