In a computer, almost everything displayed on the screen is drawn, including windows, dialog boxes, pictures, and all text, and the WM_PAINT message is Message triggered by the system when drawing these objects. Almost every operation we perform on the computer will trigger this message, and it is also one of the most important messages in Windows. This article focuses on experimenting with this message for a comprehensive study.
#define WM_PAINT 0x000F
We know that when using sendmessage/ When postmessage sends a message, it often carries two parameters, WPARAM and LPARAM, and when using GetMessage or PeekMessage to receive a message, these two parameters will also be received. Some of these messages will carry some necessary information in parameters, such as mouse position, window length and width, etc. These two parameters of WM_PAINT are empty and carry no message.
In order to obtain the trigger timing of this message, we first create a Win32 window project as the test object. The window processing function is defined as follows:
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_DESTROY: PostQuitMessage(0);//可以使GetMessage返回0 break; case WM_PAINT: { WriteConsole(hOutput,"WM_PAIN\n",10,NULL,NULL); } break; default: break; } return DefWindowProc(hWnd, uMsg, wParam, lParam); }
In our WM_PAINT processing statement, a string of "WM_PAINT\n" is written to the standard output of the console. , to verify that the WM_PAINT message is triggered. Let's verify the triggering timing of WM_PAINT respectively:
1. When the program starts, it triggers when the window is drawn.
When we start the program, because we need to draw the window, the WM_PAINT message will be triggered, and the above string will be printed:
2. When the window is resized with the mouse, it will be triggered continuously:
Since the window needs to be redrawn continuously when the window is resized, what is shown at this time is continuous triggering. WM_PAINT message:
3. The WM_PAINT message will not be triggered when minimizing, but will be triggered when restoring from minimization
The picture below is from the process of minimizing to restoring the window twice. You can see that two more strings are printed
4. The WM_PAINT message will be triggered when maximizing
When the picture is maximized and restored, the WM_PAINT message will be triggered once, as shown in the following figure:
5. When the window is dragged outside the screen, the WM_PAINT message will not be triggered, but when it is pulled back into the screen, the WM_PAINT message will be triggered continuously
The screenshot below shows that when the window is pulled back to the screen, the window is constantly redrawn, triggering the WM_PAINT message.
#6. Use the InvalidateRect function to trigger the WM_PAINT message
The function prototype of InvalidateRect As follows, each call will trigger a WM_PAINT message:
BOOL InvalidateRect( HWND hWnd, // handle of window with changed update region CONST RECT *lpRect, // address of rectangle coordinates BOOL bErase // erase-background flag );
hWnd: The handle of the form where the client area where is to be updated is located. If it is NULL, the system will redraw all windows before the function returns, and then send WM_ERASEBKGND and WM_PAINT to the window procedure processing function. lpRect: The rectangular representation of the invalid area. It is a
structure pointer that stores the size of the rectangle. If NULL, the entire window client area will be added to the update area. bErase: Indicates whether to redraw the area after the invalid rectangle is marked as valid. Use a predefined brush when redrawing. Redraw is required when TRUE is specified.
Return value:
The function returns a non-zero value if successful, otherwise it returns a zero value.
//窗口处理函数 LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_DESTROY: PostQuitMessage(0);//可以使GetMessage返回0 break; case WM_PAINT: { WriteConsole(hOutput,"WM_PAIN\n",10,NULL,NULL); } case WM_LBUTTONDOWN: { InvalidateRect(hWnd,NULL,true); } break; default: break; } return DefWindowProc(hWnd, uMsg, wParam, lParam); }
下图为执行结果,点击了3次鼠标左键,触发了3次WM_PAINT消息。
总结:
触发WM_PAINT消息的本质是改变窗口对应的显存的大小就触发一次,我们进行的每一次窗口最大化、最小化并恢复都是因为改变了窗口的显存而触发了该消息。在我们向屏幕外面拖动窗口时,这点比较特殊,窗口的显存是在一点点被擦除的,此时不会触发WM_PAINT,但是拉回窗口后,显存需要将擦除的部分重新绘制,这就又会触发一次该消息。而InvalidateRect函数,就是通过强制的清除并重绘显存来实现触发WM_PAINT消息。
我们尝试处理WM_PAINT消息,并在窗口上绘制一个矩形,绘图步骤如下:
1、开始绘图处理
HDC BeginPaint( HWND hwnd,//绘图窗口 LPPAINTSTRUCT lpPaint );
我们利用BeginPaint获取绘图设备的句柄---一个HDC对象,然后在改绘图设备上进行绘制。
2、利用HDC对象进行绘图
3、结束绘图处理
Bool EndPoint( HWND hWnd, CONST PAINTSTRUCT *lpPaint );
绘制过程参考下面的代码:
//窗口处理函数 LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_DESTROY: PostQuitMessage(0);//可以使GetMessage返回0 break; case WM_PAINT: { PAINTSTRUCT pt; HDC hdc; hdc=BeginPaint(hWnd,&pt); Rectangle(hdc,0,0,100,100); EndPaint(hWnd,&pt); } case WM_LBUTTONDOWN: { //InvalidateRect(hWnd,NULL,true); } break; default: break; } return DefWindowProc(hWnd, uMsg, wParam, lParam); }
执行结果如下,我们成功绘制了一个矩形:
The above is the detailed content of Win32 SDK Basics (12) Processing of WM_PAINT message (picture). For more information, please follow other related articles on the PHP Chinese website!