C++ Invalidaterect()函数作用案例详解
作者:HotIce0
函数原型:
BOOLInvalidateRect( HWND hWnd, // handle of window withchanged update region 窗口句柄。 CONST RECT *lpRect, // address ofrectangle coordinates rect结构体的指针。 BOOL bErase // erase-background flag 是否要发送WM_ERASEBKGND消息从而擦除原来的背景 );
这个函数的作用是,使得Client的一个矩形区域变得无效,rect结构体可以自己编辑,也可以使用GetClientRcet()来填充(这里的矩形大小Client的大小),最主要的是第三个参数,第三个参数决定了是否发送WM_ERASEBKGND消息,从而决定了是否擦除Client原有的图形。当然InvalidateRect发送WM_PAINT的形式是一种POST形式(即发送到程序消息队列),而不是像SendMessage一样直接让操作系统带着消息,调用WndProc。
当然如果想像SendMessage一样的。可以在后面接着使用UpdateWindow()直接绕过程序消息队列直接发送消息到WndProc函数,来重绘窗口。
分析一下下面的程序会更加的清晰:
case WM_RBUTTONDOWN: hdc = GetDC(hwnd); GetClientRect(hwnd, &rect); DrawText(hdc, TEXT("右键键被单机咯!"), 13, &rect, DT_VCENTER | DT_SINGLELINE); ReleaseDC(hwnd, hdc); InvalidateRect(hwnd, NULL, true); //UpdateWindow(hwnd); Sleep(1000); return 0; case WM_LBUTTONDOWN: hdc = GetDC(hwnd); GetClientRect(hwnd, &rect); DrawText(hdc, TEXT("左键被单机咯!"), 13, &rect, DT_CENTER | DT_SINGLELINE); ReleaseDC(hwnd, hdc); return 0;
这里为了能看到效果我使用了Sleep。在实际编程处理消息,不是在多线程时,这样的使用是十分愚蠢的,因为,消息循环的机制,如果你不快速的处理每一条消息。用户的体验将会受到很大的影响。比如,,无法操作,,这是最尴尬的。
1,这里如果UpdateWindow(hwnd)被注释掉的情况下,单机左键后,客户区屏幕打印出左键被单机咯,单机右键后打印出右键被单机咯。随后,调用了InvalidateRect()发送了WM_PAINT和WM_ERASEBKGND消息到消息队列,因为Invalidate第三个参数是true所以背景被重画,并且使rect的矩形范围失效。从而延迟1000ms后,处理WM_PAINT消息后,窗口上的左键…右键…..的字样都被清除。
2,如果UpdateWindow(hwnd) 没被注释掉。左键单机,右键单机,出现两条提示后,立即都消失(一般情况看不到右键点击的提示,而是直接擦除左键点击的提示的效果),为什么呢,因为UpdateWindow的作用,直接绕过队列,带到WndProc中去。所以直接重绘了。
3.如果InvalidateRect里面是false则结果将是没有任何效果。难道真的是没有效果吗。当然不是,实际上是有效果的。因为,这里InvalidateRect还是使得rect的区域失效了,只是不会擦除背景也就是原来打印在屏幕上的提示都不会被清除。而且还是发送了WM_PAINT消息,所以WM_PINT消息内的处理,会执行一次。
4.第三种情况,不就是使得区域无效,而且发送了WM_PAINT消息吗。实际上,就算不发送WM_PAINT消息,系统也会派送WM_PAINT消息。因为无效了。我又想到UpdateWindow不也是给WndPro带来了WM_PAINT消息吗?窗口不会重绘吗?答案是不会。因为窗口没有无效的区域,所以WM_PAINT内部的代码也没有执行。(为什么没有执行,原因是UpdateWindow内部检测了是否有无效区域,如果没有则不发送消息)。
到此这篇关于C++ Invalidaterect()函数作用案例详解的文章就介绍到这了,更多相关C++ Invalidaterect()函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!