在 MFC 應用中,常見需求:從對話框 A 點擊按鈕彈出對話框 B,期望 A 自動關閉,始終只保留一個對話框實例,避免多層疊加造成邏輯混亂或資源浪費。
// 對話框 A 的按鈕處理函數
void CMyDialogA::OnBnClickedButtonOpenB()
{
// 1. 先結束當前對話框 (DoModal 返回)
EndDialog(IDOK); // 或 EndDialog(IDCANCEL) 視邏輯而定
// 2. 再創建並彈出對話框 B
CMyDialogB dlgB;
dlgB.DoModal(); // 模態對話框,阻塞直到 B 關閉
// 3. B 關閉後,若需回到 A,可在這裡重新創建 A (視架構而定)
}
EndDialog 結束模態循環;非模態對話框用 DestroyWindow。EndDialog 讓 A 從堆疊彈出,再 DoModal B,否則會陷入雙重模態循環導致死鎖或界面凍結。DoModal 前透過成員變數/Setter 注入;B 關閉後需將結果回傳給呼叫者(如透過全域狀態、共享模型或回呼)。若專案有多層切換需求,建議封裝 CDialogManager 單例,統一管理對話框棧:
class CDialogManager {
std::stack m_stack;
public:
void PushDialog(CDialog* pDlg) {
if (!m_stack.empty()) m_stack.top()->EndDialog(IDOK);
m_stack.push(pDlg);
pDlg->DoModal();
m_stack.pop();
}
};
「先關舊,再開新」是 MFC 對話框切換的鐵律。善用 EndDialog 配合合理的資料流設計,即可實現乾淨、可維護的單實例對話框體驗。