MFC 提供的 AfxMessageBox 比 Win32 API MessageBox 更易用,但標準訊息方塊都需要使用者手動點擊按鈕才能關閉。實務上常有需求:只想提示使用者幾秒鐘,隨後自動消失,無需使用者確認。
雖然可自行撰寫對話框類別取代,但若專案中已大量呼叫 AfxMessageBox,逐一替換極為繁瑣。本文介紹一種更優雅的方法:覆寫 CWinApp::DoMessageBox 虛擬函數,攔截所有 AfxMessageBox 呼叫,依參數決定是否使用自訂行為。
AfxMessageBox 內部會呼叫 CWinApp::DoMessageBox:
int AFXAPI AfxMessageBox(LPCTSTR lpszText, UINT nType, UINT nIDHelp)
{
CWinApp* pApp = AfxGetApp();
if (pApp != NULL)
return pApp->DoMessageBox(lpszText, nType, nIDHelp);
else
return pApp->CWinApp::DoMessageBox(lpszText, nType, nIDHelp);
}
CWinApp::DoMessageBox 只是對 ::MessageBox 的簡單封裝。我們在衍生的 CWinApp 類別中覆寫 DoMessageBox,即可完全控制訊息方塊的行為。
在應用程式類別的標頭檔中定義新的 nType 旗標(UINT 類型,標準旗標不超過 10 個,留有大量空間):
#define MB_USERDEFINE 0x10000000
DoMessageBoxint CMyApp::DoMessageBox(LPCTSTR lpszPrompt, UINT nType, UINT nIDPrompt)
{
if (MB_USERDEFINE == nType)
{
// 呼叫自訂的訊息方塊實作(可設計為計時自動關閉)
OwnMessageBox(lpszPrompt, nType, nIDPrompt);
return TRUE;
}
// 其他類型仍使用預設行為
return CWinApp::DoMessageBox(lpszPrompt, nType, nIDPrompt);
}
void CMyDialog::OnOK()
{
// 標準訊息方塊,需使用者確認
::AfxMessageBox(_T("我是標準的 AfxMessageBox!"));
// 自訂類型,可設計為自動關閉
::AfxMessageBox(_T("我是被重載的 AfxMessageBox!"), MB_USERDEFINE);
}
OwnMessageBox 設計建議SetTimer),時間到自動 DestroyWindow。透過覆寫 DoMessageBox,我們在不修改現有呼叫碼的前提下,靈活擴展訊息方塊行為。此技巧同樣適用於其他需統一攔截 MFC 通用函數的情境。