啟動畫面不需複雜類別/執行緒。**同步阻塞**方式最簡單、最穩定:主執行緒建立視窗 → 顯示圖片/播放聲音 → Sleep(3000) → 銷毀視窗 → 進入主視窗。適用於啟動初始化快速 (<3 秒) 的中小型專案。
#include
#include // PlaySound
#pragma comment(lib, "winmm.lib")
class CSplashWindow : public CWnd {
CDC m_MemDC; CBitmap m_Bitmap; BITMAP m_bm; CBitmap* m_pOldBmp;
public:
CSplashWindow() {
m_Bitmap.LoadBitmap(MAKEINTRESOURCE(IDB_SPLASHWINDOW));
m_Bitmap.GetBitmap(&m_bm);
PlaySound(_T("SplashWindow.wav"), NULL, SND_ASYNC | SND_FILENAME);
}
~CSplashWindow() { m_MemDC.SelectObject(m_pOldBmp); }
void CreateSplash() {
CreateEx(0, AfxRegisterWndClass(0), _T("Splash"), WS_POPUP | WS_VISIBLE,
0, 0, m_bm.bmWidth, m_bm.bmHeight, NULL, NULL);
CenterWindow();
}
afx_msg void OnPaint() {
CPaintDC dc(this);
m_MemDC.CreateCompatibleDC(&dc);
m_pOldBmp = m_MemDC.SelectObject(&m_Bitmap);
dc.StretchBlt(0, 0, m_bm.bmWidth, m_bm.bmHeight,
&m_MemDC, 0, 0, m_bm.bmWidth, m_bm.bmHeight, SRCCOPY);
}
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CSplashWindow, CWnd)
ON_WM_PAINT()
END_MESSAGE_MAP()
class CMainWindow : public CFrameWnd {
public:
CMainWindow() { Create(NULL, _T("Main")); }
};
class CApp : public CWinApp {
BOOL InitInstance() {
CSplashWindow* pSplash = new CSplashWindow;
pSplash->CreateSplash();
pSplash->ShowWindow(SW_SHOW); pSplash->UpdateWindow();
Sleep(3000); // 3 秒
pSplash->DestroyWindow(); delete pSplash;
m_pMainWnd = new CMainWindow;
m_pMainWnd->ShowWindow(SW_SHOW); m_pMainWnd->UpdateWindow();
return TRUE;
}
} theApp;
| API | 用途 | 注意 |
|---|---|---|
PlaySound(..., SND_ASYNC) | 非同步播放 WAV,不阻塞 UI | 需連結 winmm.lib |
StretchBlt | 將位圖拉伸繪製到視窗 | 配合記憶體 DC 避免閃爍 |
Sleep(3000) | 阻塞主執行緒 3 秒 | 初始化耗時 >3 秒請改用執行緒版 |
WS_POPUP | 無標題列/邊框視窗 | 適合全螢幕或置中圖片 |
此時建立 Worker Thread 做初始化,UI Thread 跑啟動畫面並輪詢進度,完成後 PostMessage(WM_CLOSE) 關閉啟動畫面。
問題歡迎來信 r39710@giga.net.tw。