Win32程序不停发送WM_PAINT消息
2011-12-21 17:04
411 查看
Wn32编程中,在响应WM_PAINT消息时,很容易造成处理器使用率过高。造成处理器负载过高的原因是窗口时刻都在检查自己的Update Region,如果有则发出WM_PAINT,直到调用BeginPaint和EndPaint后才会将Update Region置空。如果在消息相应函数中没有加入BeginPaint,EndPaint 则 WM_PAINT 就会不断被发送,造成死循环。
如果不主动响应WM_PAINT,则该消息会进入DefWindowProc,它会调用那两个函数。
在MFC中也一样,一般在OnPaint中会出现CPaintDC dc(this) 该类的构造函数会调用BeginPaint,析构函数会调用EndPaint。也可能出现父类的OnPaint,如果把这些注释掉,运行后cpu占用率依旧会很高。
例如下面的一个Win32的例子,如果我们把WM_PAINT处理部分打开,就会造成负载过高。如果注释掉该代码,就没有问题。但是如果在里面添加BeginPaint以及EndPaint,那么就不会造成CPU负载过高这种问题。
如果不主动响应WM_PAINT,则该消息会进入DefWindowProc,它会调用那两个函数。
在MFC中也一样,一般在OnPaint中会出现CPaintDC dc(this) 该类的构造函数会调用BeginPaint,析构函数会调用EndPaint。也可能出现父类的OnPaint,如果把这些注释掉,运行后cpu占用率依旧会很高。
例如下面的一个Win32的例子,如果我们把WM_PAINT处理部分打开,就会造成负载过高。如果注释掉该代码,就没有问题。但是如果在里面添加BeginPaint以及EndPaint,那么就不会造成CPU负载过高这种问题。
#include <windows.h> #include <aygshell.h> #pragma comment(lib, "aygshell.lib") #define IDC_MY_STATIC 100 #define IDC_MY_BUTTON 101 #define IDC_MY_EDIT 102 LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); int _tWinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPTSTR lpszCmdLine, int nShowCmd) { WNDCLASS wc = {0}; HWND hWnd = NULL; MSG msg = {0}; DEBUGMSG(TRUE, (TEXT("hInstance=%p, lpszCmdLine=%s, nShowCmd=%d\n"), hInstance, lpszCmdLine, nShowCmd)); // 1. 注册窗口类(指定一个函数指针) wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = NULL; wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = TEXT("GWND"); if (0 == RegisterClass(&wc)) { return -1; } // 2. 创建窗口 hWnd = CreateWindow(TEXT("GWND"), TEXT("掌中"), WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); if (!IsWindow(hWnd)) { return -1; } // 3. 显示窗口 ShowWindow(hWnd, nShowCmd); UpdateWindow(hWnd); // 4. 消息循环 while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { HINSTANCE hTemp = NULL; SHINITDLGINFO shidi = {0}; WORD wID = 0; WORD wEvent = 0; DEBUGMSG(TRUE, (TEXT("hWnd=%p, uMsg=%04X, wParam=%p, lParam=%p\n"), hWnd, uMsg, wParam, lParam)); switch (uMsg) { case WM_CREATE: { hTemp = GetModuleHandle(NULL); DEBUGMSG(TRUE, (TEXT("hTemp=%p\n"), hTemp)); CreateWindow(TEXT("BUTTON"), TEXT("OPEN"), WS_CHILD | WS_VISIBLE, 10, 100, 30, 20, hWnd, (HMENU)IDC_MY_BUTTON, hTemp, NULL); DEBUGMSG(TRUE, (TEXT("WM_CREATE\n"))); shidi.dwMask = SHIDIM_FLAGS; shidi.hDlg = hWnd; shidi.dwFlags = SHIDIF_CANCELBUTTON | SHIDIF_SIZEDLGFULLSCREEN; SHInitDialog(&shidi); } break; //case WM_PAINT: // { // DEBUGMSG(TRUE, (TEXT("WM_PAINT\n"))); // } // break; case WM_COMMAND: { DEBUGMSG(TRUE, (TEXT("WM_COMMAND\n"))); wID = LOWORD(wParam); wEvent = HIWORD(wParam); switch (wID) { case IDCANCEL: { DestroyWindow(hWnd); } break; case IDC_MY_BUTTON: { MessageBox(hWnd, TEXT("HI"), TEXT("Tip"), MB_OK); } break; } } break; case WM_DESTROY: { DEBUGMSG(TRUE, (TEXT("WM_DESTROY\n"))); PostQuitMessage(0); } break; case WM_KEYDOWN: { DEBUGMSG(TRUE, (TEXT("WM_KEYDOWN\n"))); } break; case WM_KEYUP: { DEBUGMSG(TRUE, (TEXT("WM_KEYUP\n"))); } break; case WM_CHAR: { DEBUGMSG(TRUE, (TEXT("WM_CHAR\n"))); } break; case WM_LBUTTONDOWN: { DEBUGMSG(TRUE, (TEXT("WM_LBUTTONDOWN\n"))); } break; case WM_LBUTTONUP: { DEBUGMSG(TRUE, (TEXT("WM_LBUTTONUP\n"))); } break; case WM_INITDIALOG: { DEBUGMSG(TRUE, (TEXT("WM_INITDIALOG\n"))); } break; case WM_SYSKEYDOWN: { DEBUGMSG(TRUE, (TEXT("WM_SYSKEYDOWN\n"))); } break; default: return DefWindowProc(hWnd, uMsg, wParam, lParam); } return 0; }
相关文章推荐
- Win32控件--------------------WM_DRAWITEM消息测试程序
- 发送消息执行记事本的“另存为”菜单功能(通过WM_COMMAND控制使用别的程序的菜单命令)
- 使用SendMessage方法对窗体上的控件进行截图,该方法的思想就是把控件的句柄拿到,对控件发送WM_PAINT消息,并且把希望得到图形对象的句柄当作wParam参数传过去,这样就可以在图形对象得到想要得图形。
- 系统何时发送WM_PAINT消息?
- SDK编程中有效区域与无效区域的盲区WM_PAINT消息何时发送的。。。
- 用非管理员权限启动主程序,并用管理员权限启动子程序,导致WM_COPYDATA消息发送失败的问题
- SDK编程中有效区域与无效区域的盲区WM_PAINT消息何时发送的。。。
- DoModal 的调用会发送 WM_INITDIALOG 消息 WM_ERASEBKG 先于WM_PAINT
- SDK编程中有效区域与无效区域的盲区WM_PAINT消息何时发送的。。。
- Invalidate(TRUE)与Invalidate(FALSE)区别(前者会发送WM_ERASEBKGND消息全部刷新,然后使用WM_PAINT消息绘制,而后者只发送WM_PAINT消息)
- 系统何时发送WM_PAINT消息
- Win32 SDK基础(12)—— WM_PAINT消息的处理
- 用非管理员权限启动主程序,并用管理员权限启动子程序,导致WM_COPYDATA消息发送失败的问题
- SendMessage发送WM_COMMAND消息控制另一个程序的某一个按钮
- 使用API函数发送消息关闭程序:WM_CLOSE=0x0010;
- Win32程序中为什么不能响应WM_KEYDOWN消息
- 用非管理员权限启动主程序,并用管理员权限启动子程序,导致WM_COPYDATA消息发送失败的问题
- 用代码关闭程序的正确做法!---向窗口发送WM_CLOSE消息
- 用代码关闭程序的正确做法!---向窗口发送WM_CLOSE消息
- mfc编程之发送wm_paint消息时绘图界面只出现一瞬间