Splash Screen (啟動封面) 不僅美化啟動體驗,還能掩蓋主視窗初始化耗時。本文示範純 MFC + Windows 訊息機制實作,無需額外執行緒,邏輯清晰可控。
ClassView → `CMainFrame` 右鍵 `Add Member Variable...`:
`Splash.cpp` 加入 `#include "SplashDlg.h"`。
ClassWizard → `CMainFrame` → `WM_TIMER` → `Add Function` → `OnTimer`。
void CMainFrame::OnTimer(UINT nIDEvent) {
if (nIDEvent == 1) {
if (splash->IsWindowVisible()) {
// 啟動畫面可見:置頂、刷新、停留 2 秒、發送關閉
splash->SetActiveWindow();
splash->UpdateWindow();
Sleep(2000); // 停留時間 (可配置)
splash->SendMessage(WM_CLOSE);
}
else {
// 啟動畫面已關閉:主視窗置頂、殺死定時器
SetActiveWindow();
KillTimer(1);
}
}
// CFrameWnd::OnTimer(nIDEvent); // 視需求決定是否呼叫基類
}
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) {
// 1. 最早啟動定時器 (ID=1, 間隔 5ms,頻率不宜過高)
SetTimer(1, 5, NULL);
// 2. 建立並顯示啟動畫面
splash = new CSplashDlg();
// 可選:播放歡迎音效
// sndPlaySound("welcome.wav", SND_ASYNC);
// PlaySound("welcome.wav", NULL, SND_ASYNC);
splash->Create(IDD_DIALOG1);
splash->ShowWindow(SW_SHOW);
splash->UpdateWindow();
// 3. 標準主視窗初始化
if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1;
// 工具列、狀態列建立...
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) {
TRACE0("Failed to create toolbar\n"); return -1;
}
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) {
TRACE0("Failed to create status bar\n"); return -1;
}
// 停靠設定...
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
// 主視窗置中顯示
CenterWindow();
return 0;
}
| 要點 | 說明 |
|---|---|
| 定時器優先啟動 | `SetTimer` 放在 `OnCreate` 最開頭,確保 Splash 顯示後即受控制 |
| 無模式對話框 | `Create` + `ShowWindow` 非阻塞,主視窗初始化並行 |
| 訊息驅動狀態機 | `WM_TIMER` 週期性檢查可見性,單一職責,無執行緒同步煩惱 |
| Sleep 阻塞在 UI 執行緒 | 此處 `Sleep(2000)` 可接受,因主視窗尚未顯示;若需響應改用額外定時器 |
| 資源清理 | 主視窗銷毀時記得 `delete splash;` (析構函數中處理) |
編譯連結執行,專屬啟動畫面即呈現眼前。此純訊息機制實作簡單可靠,適合中小型 MFC 專案快速集成。