Visual C++ AppWizard 內建 Splash Screen 元件 (CSplashWnd),但僅支援 SDI/MDI 專案,對話方塊專案需手動移植。本文深入剖析 CSplashWnd 運作機制 (靜態指標、定時器自毀、訊息轉發),並提供對話方塊專案完整整合步驟。
CWinApp::InitInstance 呼叫 CSplashWnd::EnableSplashScreen(TRUE) 設定旗標。CMainFrame::OnCreate 呼叫 CSplashWnd::ShowSplashScreen(this):
CSplashWnd 物件 (靜態指標 c_pSplashWnd)。IDB_SPLASH,依圖片尺寸 CreateEx 建立 WS_POPUP | WS_VISIBLE 視窗。CenterWindow 置中、SetTimer(1, 750, NULL) 設定 750ms 定時器。CSplashWnd::OnTimer 觸發 → HideSplashScreen() → DestroyWindow()、AfxGetMainWnd()->UpdateWindow()。CWinApp::PreTranslateMessage 攔截鍵盤/滑鼠訊息 → CSplashWnd::PreTranslateAppMessage → 若為輸入訊息則提前銷毀 Splash。Splash.h、Splash.cpp 至對話方塊專案目錄。IDB_SPLASH。
BOOL CMyApp::InitInstance() {
// ...
CSplashWnd::EnableSplashScreen(TRUE); // 關鍵:啟用旗標
// ...
return TRUE;
}
BOOL CMyApp::PreTranslateMessage(MSG* pMsg) {
if (CSplashWnd::PreTranslateAppMessage(pMsg)) return TRUE;
return CWinApp::PreTranslateMessage(pMsg);
}
WM_CREATE 處理函式 OnCreate。
int CMyDialog::OnCreate(LPCREATESTRUCT lpCreateStruct) {
if (CDialog::OnCreate(lpCreateStruct) == -1) return -1;
CSplashWnd::ShowSplashScreen(this); // this = 對話框視窗作為父視窗
return 0;
}
在 MyApp.cpp、MyDialog.cpp 頂端加入 #include "Splash.h"。
CSplashWnd::Create 載入位圖後,取得 CDC 繪製使用者名稱、版本號等資訊。SetTimer(1, 3000, NULL) 延長至 3 秒。OnTimer 配合 SetLayeredWindowAttributes (WS_EX_LAYERED) 實現 Alpha 混合動畫。| 現象 | 原因 | 解決 |
|---|---|---|
| Splash 不顯示 | 未呼叫 EnableSplashScreen(TRUE) 或 IDB_SPLASH 遺漏 | 檢查資源 ID、InitInstance 順序 |
| 閃爍/殘影 | 位圖未含遮罩、背景未正確擦除 | 確保位圖透明色正確、或啟用 WS_EX_LAYERED |
| 對話方塊專案編譯錯誤 | CSplashWnd 使用 CFrameWnd 專有成員 | 檢查 Splash.cpp 是否有 SDI 專用代碼 (如 m_pMainWnd 轉型) |