在 MFC 多文件應用程式(MDI)啟動時,需先顯示授權/登入驗證對話框;驗證通過才進入主程式流程,否則結束應用程式。開發者常在 InitInstance() 中錯誤設定 m_pMainWnd 導致主視窗無法正常建立。
CLicenseDlg dlg;
m_pMainWnd = &dlg; // ❌ 錯誤:指向棧上暫時物件,函式結束後失效
CLicenseDlg *log = new CLicenseDlg;
if (log->DoModal() != IDOK) {
return FALSE;
}
// ... 後續缺少正確建立主框架視窗流程
主要問題:m_pMainWnd 指向區域變數 dlg,函式返回後記憶體釋放,導致框架視窗建立失敗。
BOOL CMyApp::InitInstance()
{
// 1. 先顯示驗證對話框(不設為 m_pMainWnd)
CLicenseDlg dlg;
if (dlg.DoModal() != IDOK) {
return FALSE; // 驗證失敗,直接結束應用程式
}
// 2. 驗證通過,正常建立 MDI 架構
// 註冊文件樣板、建立主框架視窗...
CMultiDocTemplate* pDocTemplate = new CMultiDocTemplate(
IDR_MYTYPE,
RUNTIME_CLASS(CMyDoc),
RUNTIME_CLASS(CChildFrame),
RUNTIME_CLASS(CMyView));
AddDocTemplate(pDocTemplate);
// 建立主框架視窗
CMainFrame* pMainFrame = new CMainFrame;
if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
return FALSE;
m_pMainWnd = pMainFrame; // ✅ 正確指向堆疊配置的主框架
// 顯示主視窗
pMainFrame->ShowWindow(m_nCmdShow);
pMainFrame->UpdateWindow();
return TRUE;
}
m_pMainWnd:它只是啟動階段的模態對話框,用區域變數 CLicenseDlg dlg; 即可,生命週期隨 InitInstance 結束而結束。new CMainFrame,並將指標指派給 m_pMainWnd,MFC 會在應用程式結束時自動釋放。return FALSE:不需建立任何視窗,乾淨結束。BOOL CMyApp::VerifyLicense()
{
CLicenseDlg dlg;
return dlg.DoModal() == IDOK;
}
BOOL CMyApp::InitInstance()
{
if (!VerifyLicense()) return FALSE;
// ... 正常 MDI 初始化流程
}
這樣能讓 InitInstance 保持簡潔,驗證邏輯可單元測試。
MFC MDI 應用程式整合啟動驗證對話框的核心原則是:「驗證對話框與主框架視窗分離,m_pMainWnd 僅指向真正的主框架視窗」。遵循此模式可避免視窗建立失敗、記憶體洩漏等常見問題。