更安全的DoEvents函数
- C/C++ code
inline void DoEvents(){ MSG msg; //定义一个MSG类型的变量,不多解释 while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) //获取消息并把该消息从消息队列中移除(防止重复响应)。 { DispatchMessage(&msg); //将消息移交给过程函数 TranslateMessage(&msg);//翻译消息 在合适的机会产生char消息 } }分析:DoEvents函数相当于是一个消息循环,可以在耗时运算里使用来解决假死的问题。
示例:
我想延迟2秒弹出信息框:
- C/C++ code
Sleep(2000;)//延迟2秒 MessageBox("已经延迟2秒","信息:",MB_OK);这样一来,调用Sleep时窗口就会假死,为了在不引入多线程编程的前提下解决这个问题,那就可以使用 DoEvents函数来实现
- C/C++ code
for (int i=1;i<=100;i++){Sleep (20);Doevent();}MessageBox("已经延迟2秒","信息:",MB_OK);代码分析,虽然在执行以上代码时窗口的消息循环函数会被堵塞,但是程序在每延迟20ms会进行一次检查并响应消息(将消息移交给过程函数处理),充当着一个消息循环的角色,窗口消息能获得及时的响应,程序自然不会假死,执行100次Sleep(20);就等价于Sleep(2000);。而DoEvents ();耗时可以忽略。
然而,以上代码有一个不足,那就是
- C/C++ code
PeekMessage(&msg,NULL,0,0,PM_REMOVE)
的消息获取方式可能会接收到非窗体消息(其他线程消息),以下代码可以完美解决这个问题。
- C/C++ code
#include "windows.h"BOOL CALLBACK EnumWindows1(HWND hwnd, LPARAM lParam);BOOL CALLBACK EnumWindows2(HWND hwnd, LPARAM lParam);void SafeDoevents ();//================================================================void SafeDoevents(){ EnumThreadWindows(GetCurrentThreadId(),EnumWindows1,0);};inline void DoWindowEvent(HWND m_hWnd){ MSG msg; while(PeekMessage(&msg,m_hWnd,0,0,PM_REMOVE)) //获取消息并从消息队列中删除(防止重复响应)。 { DispatchMessage(&msg); //将消息移交给过程函数 TranslateMessage(&msg);//翻译消息 在合适的机会产生char消息 }}BOOL CALLBACK EnumWindows1(HWND hwnd,LPARAM lParam){ DoWindowEvent(hwnd); EnumChildWindows(hwnd,EnumWindows2,0); return true;}BOOL CALLBACK EnumWindows2(HWND hwnd,LPARAM lParam){ DoWindowEvent(hwnd); return true;}[解决办法]
[解决办法]
TranslateMessage应该在DispatchMessage前面