关于WM_PAINT消息中只重绘无效区的问题

来源:互联网 发布:hadoop java开发实例 编辑:程序博客网 时间:2024/06/03 15:05

一直以来我都有一个疑问,那就是下面的代码

case WM_PAINT :hdc = BeginPaint (hwnd, &ps);                ...............EndPaint (hwnd, &ps) ;return 0 ;

其中的BeginPaint(hwnd,&ps)通过ps结构体中的一个矩形结构体变量标识的无效区来重绘窗口,而且重点是只重绘无效区。

那么如果我代码中的省略处的代码在整个窗口上绘制,难道窗口无效时发送WM_PAINT消息就只重绘无效区吗?

Windows系统真可谓博大精深,想要了解个透彻真可谓不易啊!不过我一直都在努力着去了解的更深刻,菜鸟不停的飞,总有一天会飞成老鸟的,因为岁月不饶人吗!嘿嘿。

学习Windows程序设计的过程中总会有这样那样的疑问,我那愚钝的脑袋一时半会真的很难解决,不过人家系统那样搞自然会有它的依据,只是现在自己知识浅薄,看不透人家那样做的原因。所以把遇到的问题记录下来,好让顿悟的那天有个翻查记录的机会。

也许你也有同样的困惑,但是人家系统确实是那样做的。不信,咱们拿一个程序试试,便一切都了然了

#include <windows.h>#define ID_TIMER    1LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,                    PSTR szCmdLine, int iCmdShow){static TCHAR szAppName[] = TEXT ("Beeper1") ;HWND         hwnd ;MSG          msg ;WNDCLASS     wndclass ;wndclass.style         = CS_HREDRAW | CS_VREDRAW ;wndclass.lpfnWndProc   = WndProc ;wndclass.cbClsExtra    = 0 ;wndclass.cbWndExtra    = 0 ;wndclass.hInstance     = hInstance ;wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;wndclass.lpszMenuName  = NULL ;wndclass.lpszClassName = szAppName ;if (!RegisterClass (&wndclass)){MessageBox (NULL, TEXT ("Program requires Windows NT!"), szAppName, MB_ICONERROR) ;return 0 ;}hwnd = CreateWindow (szAppName, TEXT ("Beeper1 Timer Demo"),WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,NULL, NULL, hInstance, NULL) ;ShowWindow (hwnd, iCmdShow) ;UpdateWindow (hwnd) ;while (GetMessage (&msg, NULL, 0, 0)){TranslateMessage (&msg) ;DispatchMessage (&msg) ;}return msg.wParam ;}LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){static BOOL fFlipFlop = FALSE ;HBRUSH      hBrush ;HDC         hdc ;PAINTSTRUCT ps ;RECT        rc, rect;rect.left= 100;   //在这里设定一个矩形区域,当做无效区rect.top= 100;rect.right= 500;rect.bottom= 500;switch (message){case WM_CREATE:SetTimer (hwnd, ID_TIMER, 1000, NULL) ;//这里设置一个定时器,每隔1s发送一个WM_TIMER消息return 0 ;case WM_TIMER :MessageBeep (-1);          fFlipFlop = !fFlipFlop ;InvalidateRect (hwnd, &rect, FALSE);                //这里我们在每一次接受一个WM_TIMER消息时,就通过这个调用使rect标识的矩形区域标识为无效                //窗口出现无效区时会向消息队列中发送WM_PAINT                //按照hdc = BeginPaint (hwnd, &ps);会使无效区域有效,也即是通过只重绘无效区域使窗口变的有效//我们在WM_PAINT消息中调用FillRect (hdc, &rc, hBrush);让rc标识整个窗口客户区,也就是绘制整个窗口客户区                //我们通过fFlipFlop来决定绘制蓝色还是红色                //运行程序你发现窗口中只在左上角的标识的无效矩形区域出现红色,其它区域永远都是蓝色                //由此可以说明WM_PAINT消息中确实只重绘无效区                return 0 ;case WM_PAINT :hdc = BeginPaint (hwnd, &ps) ;GetClientRect (hwnd, &rc) ;hBrush = CreateSolidBrush (fFlipFlop ? RGB(255,0,0) : RGB(0,0,255)) ;//Sleep(1000);FillRect (hdc, &rc, hBrush) ;EndPaint (hwnd, &ps) ;DeleteObject (hBrush) ;return 0 ;/*通过这段代码可以测试WM_TIMER消息的优先级比较低case WM_LBUTTONDOWN:Sleep(5000);//WM_TIMER消息的优先级比较低return 0 ;*/case WM_DESTROY :KillTimer (hwnd, ID_TIMER) ;//清除定时器一定不能忘PostQuitMessage (0) ;return 0 ;}return DefWindowProc (hwnd, message, wParam, lParam) ;}


你也可以把代码拷贝到你的编译器里面试一试,看看究竟是怎样的!


原创粉丝点击