模態對話框中,當焦點不在按鈕上時(如編輯框),按 Enter 或 ESC 會觸發預設 OnOK / OnCancel 導致對話框關閉。若需自行驗證或阻止關閉,必須覆寫這兩個虛函數。
class CGuessDlg : public CDialog
{
// ...
protected:
virtual void OnOK(); // 覆寫 Enter 鍵行為
virtual void OnCancel(); // 覆寫 ESC 鍵行為
// ...
};
void CGuessDlg::OnOK()
{
// 範例:驗證輸入後才允許關閉
UpdateData(TRUE); // 從控制項取得資料
if (m_strInput.IsEmpty())
{
AfxMessageBox(_T("請輸入內容!"));
return; // 不呼叫 CDialog::OnOK(),對話框不關閉
}
// 驗證通過,呼叫基類關閉並回傳 IDOK
CDialog::OnOK();
}
void CGuessDlg::OnCancel()
{
// 範例:確認後才取消
if (AfxMessageBox(_T("確定要放棄輸入嗎?"), MB_YESNO | MB_ICONQUESTION) == IDYES)
{
CDialog::OnCancel(); // 呼叫基類關閉並回傳 IDCANCEL
}
// 否則不處理,對話框保持開啟
}
CDialog::PreTranslateMessage 中處理 Enter/ESC,分別呼叫 OnOK/OnCancel。OnOK 執行 UpdateData(TRUE) 並 EndDialog(IDOK);OnCancel 直接 EndDialog(IDCANCEL)。IDOK)。IDCANCEL → 自動成為 ESC 觸發目標。IDOK/IDCANCEL 按鈕,系統仍會呼叫 OnOK/OnCancel,故覆寫更為可靠。上一篇筆記的「體育彩票選號器」對話框僅有「選號」按鈕(非 IDOK),若使用者在編輯框按 Enter 會意外關閉。套用上述覆寫即可解決:
void CGuessDlg::OnOK()
{
// 只有點擊「選號」按鈕才產生號碼,Enter 鍵不處理
// 直接 return 防止關閉
return;
}
void CGuessDlg::OnCancel()
{
// ESC 鍵彈出確認對話框
if (AfxMessageBox(_T("確定離開選號器?"), MB_YESNO) == IDYES)
CDialog::OnCancel();
}
OnOK/OnCancel 是控制模態對話框關閉行為的標準做法。virtual 宣告,實作檔中視邏輯決定是否呼叫基類。UpdateData、驗證邏輯、確認對話框,構建健壯的使用者互動流程。掌握此技巧,即可避免使用者誤觸鍵盤導致資料遺失或流程中斷,提升應用程式專業度。