當人們使用軟體時,大多數是想看到自己所需要的結果,比如玩 RPG 遊戲,就是想看到自己所操作的主角做各種各樣的事情。在 2D 的 RPG 遊戲裡,其實做的事情,就是不斷地更新畫面,也就是不斷地顯示 BMP 的圖檔。在普通的程式裡,大多也是顯示各種文本和圖檔的,但是有一種類型的應用程式是不怎麼顯示結果的,那就是服務程式。不管怎麼樣,隻要我們想看到程式所執行後的結果,就需要在程式裡顯示出來。也就是需要調用 BeginPaint 和 EndPaint 函數。 BeginPaint 函數的作用是告訴 Windows 系統,要開始向顯示卡輸出内容了,把這次顯示的操作請求放到系統顯示隊列裡。由于系統上的顯示卡往往隻有一個,那麼這種資源是獨占的,是以作業系統會讓顯示操作線性化,保證每個視窗的顯示是獨立進行的,而不是 A 視窗顯示一部份,或者 B 視窗顯示一部份,而是 A 視窗顯示完成後再讓 B 視窗顯示。是以, BeginPaint 函數就是跟作業系統說,我需要顯示了,你安排好吧。當 BeginPaint 傳回時,就擷取到系統的顯示資源句柄,這樣就可以調 GDI 一大堆函數來操作了。顯示完成後,一定要記得調用函數 EndPaint ,因為使用 BeginPaint 函數請求了獨占的顯示資源後,如果不釋放回去,就會讓其它程式永遠擷取不到顯示資源了,這樣系統就死鎖了。如果你有空仔細地檢視一下 Windows 源程式,就會發現 BeginPaint 函數和 EndPaint 函數怎樣構成的。比如在調用 BeginPaint 函數時先把光标隐藏起來,接着再顯示使用者顯示的東西,最後調用 EndPaint 函數後,又把隐藏的光标顯示出來。 函數 BeginPaint 函數和 EndPaint 函數聲明如下: WINUSERAPI HDC WINAPI BeginPaint( __in HWND hWnd, __out LPPAINTSTRUCT lpPaint); WINUSERAPI BOOL WINAPI EndPaint( __in HWND hWnd, __in CONST PAINTSTRUCT *lpPaint); hWnd 是視窗句柄。 lpPaint 是擷取顯示參數。它的結構定義如下: typedef struct tagPAINTSTRUCT { HDC hdc; BOOL fErase; RECT rcPaint; BOOL fRestore; BOOL fIncUpdate; BYTE rgbReserved[32]; } PAINTSTRUCT, *PPAINTSTRUCT; hdc 是擷取裝置句柄。 fErase 是否擦新背景。 rcPaint 是顯示的視窗大小。 fRestore 、 fIncUpdate 、 rgbReserved 是保留使用的參數。 BeginPaint 函數的傳回值也是顯示裝置的句柄。 調用這個函數的例子如下:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 菜單選項指令響應 : switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }