許多商業軟體需在啟動時驗證使用者身分,僅允許合法帳密進入系統。本文示範在 MFC SDI 架構下,於 CView::OnInitialUpdate 彈出模態登入對話框,驗證失敗則循環提示或取消啟動,成功才讓主視窗顯示。
CLoginTestApp (衍生 CWinApp) 新增 BOOL m_bSuccessLogin 標記登入狀態。CLoginTestView::OnInitialUpdate 執行登入邏輯(最早可攔截視窗顯示的虛擬函式)。InitInstance 根據 m_bSuccessLogin 決定是否 ShowWindow 主視窗,否則銷毀視窗並返回 FALSE 終止應用程式。class CLoginDlg : public CDialog {
public:
CString m_strUserName, m_strUserPwd;
BOOL m_bCancel = FALSE;
// DDX 控制項綁定...
afx_msg void OnCancel() { m_bCancel = TRUE; CDialog::OnCancel(); }
};
void CLoginTestView::OnInitialUpdate() {
CView::OnInitialUpdate();
CLoginTestApp* pApp = (CLoginTestApp*)AfxGetApp();
CLoginDlg dlg;
while (true) {
dlg.m_strUserName = dlg.m_strUserPwd = _T("");
if (dlg.DoModal() != IDOK) { // 使用者按取消
pApp->m_bSuccessLogin = FALSE;
return;
}
// 簡單驗證:帳號 aa / 密碼 bb
if (dlg.m_strUserName == _T("aa") && dlg.m_strUserPwd == _T("bb")) {
pApp->m_bSuccessLogin = TRUE;
return;
}
AfxMessageBox(_T("帳號或密碼錯誤!"));
// 循環重試
}
}
BOOL CLoginTestApp::InitInstance() {
// ... 標準初始化 ...
CSingleDocTemplate* pDocTemplate = new CSingleDocTemplate(...);
AddDocTemplate(pDocTemplate);
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
if (!ProcessShellCommand(cmdInfo)) return FALSE; // 建立主視窗但未顯示
// 關鍵:根據登入結果決定是否顯示
if (m_bSuccessLogin) {
m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);
m_pMainWnd->UpdateWindow();
return TRUE;
} else {
delete m_pMainWnd; // 銷毀已建立的主視窗
m_pMainWnd = NULL;
return FALSE; // 終止應用程式
}
}
InitInstance 建立 Doc/View/Frame 架構,ProcessShellCommand 完成主視窗建立(但未 ShowWindow)。OnInitialUpdate 被呼叫,彈出模態登入對話框(阻塞主執行緒)。m_bSuccessLogin=TRUE → 返回 InitInstance → ShowWindow 主視窗。m_bSuccessLogin=FALSE → 返回 InitInstance → 刪除主視窗 → 返回 FALSE → 應用程式退出。
圖 1:登入對話框,輸入 aa/bb 即可進入
| 優點 | 缺點 |
|---|---|
| 邏輯簡單、MFC 原生、無需額外執行緒 | 僅適用 SDI/MDI 架構,對話框式專案需調整 |
| 主視窗完全不顯示,無閃爍 | 阻塞主執行緒,無法顯示啟動畫面/進度條 |
| 易於擴充驗證邏輯 | 若登入需網路請求,會凍結 UI,建議改用非同步模式 |
利用 CView::OnInitialUpdate 早期攔截點與 CWinApp::m_bSuccessLogin 狀態旗標,即可以極少代碼實現啟動強制登入。此模式適用於桌面端工具、內部管理系統等需輕量級存取控制的場景。完整專案已在 VS.NET / VC6.0 / Win98/2K/XP 測試通過。