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