DoModal() 直到對話框關閉才返回。void CYourView::OnOpenModalDlg()
{
CYourDlg dlg; // 棧上建立
INT_PTR nResult = dlg.DoModal(); // 進入訊息迴圈,阻塞此處
// 只有使用者關閉對話框後才會執行到這裡
switch (nResult)
{
case IDOK:
// 使用者按「確定」或呼叫 OnOK()
TRACE(_T("使用者確認\n"));
break;
case IDCANCEL:
// 使用者按「取消」、Esc 鍵、關閉按鈕或呼叫 OnCancel()
TRACE(_T("使用者取消\n"));
break;
case -1:
// DoModal 內部錯誤(資源不足、模板找不到等)
AfxMessageBox(_T("對話框建立失敗"));
break;
default:
// 自訂回傳值(呼叫 EndDialog(nCustomValue))
TRACE(_T("自訂返回值: %d\n"), nResult);
break;
}
}
DoModal() 回傳值詳細說明| 回傳值 | 來源 | 典型用途 |
|---|---|---|
IDOK (1) | 使用者按下預設按鈕(IDOK)、呼叫 OnOK() | 確認設定、儲存資料 |
IDCANCEL (2) | 使用者按 Esc、關閉視窗、呼叫 OnCancel() | 放棄變更 |
-1 | DoModal() 內部失敗 | 錯誤處理 |
| 自訂整數 | 呼叫 EndDialog(nResult) | 多按鈕對話框區分動作(如「另存新檔」、「覆蓋」、「取消」) |
EndDialog()// 對話框類別內部
void CTestDlg::OnBtnSaveAndClose()
{
// 驗證資料...
if (!UpdateData(TRUE)) return; // 驗證失敗不關閉
EndDialog(ID_SAVE_AND_CLOSE); // 自訂回傳值,需在 resource.h 定義
}
void CTestDlg::OnBtnDiscard()
{
EndDialog(ID_DISCARD_CHANGES);
}
// 呼叫端處理
INT_PTR nRet = dlg.DoModal();
if (nRet == ID_SAVE_AND_CLOSE) { /* 儲存並關閉 */ }
else if (nRet == ID_DISCARD_CHANGES) { /* 捨棄 */ }
OnOK()/OnCancel() 的正確姿勢void CTestDlg::OnOK()
{
// 1. 先做資料驗證/存取
if (!UpdateData(TRUE)) // 失敗:DDV 驗證未過,焦點已導向錯誤控件
return; // 【關鍵】直接返回,不呼叫基類,對話框保持開啟
// 2. 額外業務邏輯檢查
if (m_strPassword != m_strConfirmPwd)
{
AfxMessageBox(_T("兩次密碼不一致"));
GetDlgItem(IDC_CONFIRM_PWD)->SetFocus();
return;
}
// 3. 一切正常,呼叫基類關閉對話框(內部會呼叫 EndDialog(IDOK))
CDialog::OnOK();
}
void CTestDlg::OnCancel()
{
// 通常不需額外邏輯,直接呼叫基類
// 若需確認「確定放棄?」可在這裡加詢問
if (AfxMessageBox(_T("確定放棄變更?"), MB_YESNO) == IDYES)
CDialog::OnCancel();
}
OnInitDialog 呼叫 EndDialog:對話框一閃即關,DoModal 返回對應值。可用於「無權限直接關閉」等場景。DoModal:在有模式對話框中再開啟另一個有模式對話框完全合法(如檔案開啟對話框),內層關閉後外層繼續運行。DoModal:MFC UI 物件具有執行緒親和性,必須在建立該物件的執行緒呼叫。DoModal 返回 -1,TRACE 輸出「Dialog template not found」。// 對話框類
class CDataDlg : public CDialog
{
CString m_strName;
int m_nAge;
// ...
virtual void DoDataExchange(CDataExchange* pDX);
};
void CDataDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT_NAME, m_strName);
DDV_MaxChars(pDX, m_strName, 20);
DDX_Text(pDX, IDC_EDIT_AGE, m_nAge);
DDV_MinMaxInt(pDX, m_nAge, 1, 120);
}
// 呼叫端
void CMainView::OnEditData()
{
CDataDlg dlg;
dlg.m_strName = m_currentName; // 傳入初始值
dlg.m_nAge = m_currentAge;
if (dlg.DoModal() == IDOK)
{
// 使用者按確定且驗證通過,取回資料
m_currentName = dlg.m_strName;
m_currentAge = dlg.m_nAge;
UpdateViews(); // 刷新顯示
}
// 若取消,dlg 解構,成員變量銷毀,原資料不變
}
有模式對話框建立/銷毀開銷較大(載入資源、建立視窗、訊息迴圈)。對於頻繁彈出的小型對話框(如工具提示、顏色選擇器),考慮:
CPropertySheet 頁籤整合多個子對話框DoModal(需手動重置資料)