GDI 設備環境句柄(2)
阿新 • • 發佈:2018-05-23
BE round 背景 狀態 信息 lld style 景區 def
WM_PAINT 消息的觸發
Windows 程序在以下情況會觸發WM_PAINT消息:
- 窗口被移動導致被遮蓋部分暴露出來
- 用戶調整窗口的大小(當窗口類的 style 字段被設置為 CS_HREDRAW 和 CS_VREDRAW)
- 調用 ScrollWindow 或 ScrollDC 函數滾動客戶區
- 調用 InvalidateRect 或 InvalidateRgn 函數生成 WM_PAINT
獲取設備環境句柄
需要在屏幕上繪圖的時候,需要先獲取到設備環境句柄,這裏有兩種方式:
1、調用 BeginPaint 函數(用於響應 WM_PAINT 消息)
第一個參數是當前的窗口句柄,第二個參數是 PAINTSTRUCT 結構的地址,它將返回一個設備環境句柄。BeginPaint 函數的原型如下:
HDC BeginPaint( HWND hwnd, // 當前的窗口句柄 LPPAINTSTRUCT lpPaint // PAINTSTRUCT 結構的地址 )
Windows 為每個窗口維護一個“繪制信息結構”,即 PAINTSTRUCT,這裏給出了它的定義:
typedef struct tagPAINTSTRUCT { HDC hdc; // 設備環境句柄,即 BeginPaint 函數的返回值 BOOL fErase; // 背景刷狀態,如果為 TRUE,表示無效背景區域需要進行擦除,為 FALSE,表示已經擦除了無效區域的背景RECT rcPaint; // 無效矩形邊界,是一個 RECT 結構,包含 left、top、right、bottom 四個參數 BOOL fRestore; BOOL fIncUpdate; BYTE rgbReserved[32]; } PAINTSTRUCT;
調用 BeginPaint 函數時,PAINTSTRUCT 結構中的字段將被自動填充。
當調用 BeginPaint 函數獲得設備環境句柄,並處理 WM_PAINT 消息後,必須使用 EndPaint 函數釋放獲取到的設備環境句柄,該函數原型如下:
BOOL EndPaint( HWND hWnd,// 當前的窗口句柄 CONST PAINTSTRUCT *lpPaint // PAINTSTRUCT 結構的地址 );
源碼片段示例:
// ...... case WM_PAINT: hdc = BeginPaint(hwnd, &ps); // 其他GDI代碼 EndPaint(hwnd, &ps); return 0; // ......
2、調用 GetDC 函數(用於響應非 WM_PAINT 消息)
GetDC 函數只有一個參數,即當前的窗口句柄,它將設備環境句柄作為返回值返回。在使用完設備環境句柄後,必須調用 ReleaseDC 函數將其釋放,它有兩個參數,第一個是當前的窗口句柄,第二個是要釋放的設備環境句柄。
源碼片段示例:
// ...... hdc = GetDC(hwnd); // 其他GDI代碼 ReleaseDC(hwnd, hdc); return 0; // ......
GetDC / ReleaseDC 組合通常用於處理鍵盤消息或(與)鼠標消息。
需要註意的地方(小結)
- WM_PAINT 消息的產生,表示窗口客戶區需要重繪。
- BeginPaint 函數返回的是無效矩形客戶區(PAINTSTRUCT 結構中的 rcPaint 字段)的設備環境句柄,而 GetDC 函數返回的是整個客戶區的設備環境句柄。
- BeginPaint 函數調用後,無效矩形區域將變得有效化;而 GetDC 函數本身不會使客戶區無效區域有效化,需要自行調用 ValidateRect 函數使客戶區無效區域有效化。
GDI 設備環境句柄(2)