关于自封装的消息循环函数的改进问题
各位高手, 本人利用AfxBeginThread开辟了一个UI线程,并自写了一个消息循环函数,希望以后可以封装入DLL内。
上网搜索了不少例子,但都感觉讲的不够详细,在此把自己写的贴出来,当然这个函数存在一定的缺陷,感觉有点冗繁,希望大家指正。
改进后也方便其他人学习参考。
如下代码:
BOOL CTestDlg::DoLoop()
{
MSG msg;
BOOL bRet;
while(1)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))// 从Windows消息队列中取出消息
{
bRet = GetMessage(&msg, NULL, 0, 0);
if(bRet != 0)
{
if(bRet == -1)//判断返回值是否有问题
{
AfxMessageBox(_T("Handle the error and possibly exit!"));
break;
}else{//以下分情况讨论获取到的消息对应什么操作
switch(msg.message)
{
case WM_CLOSE:
DestroyWindow();
break;
case WM_DESTROY:
delete this;
PostQuitMessage(0);
break;
default:
TranslateMessage(&msg);
DispatchMessage(&msg);
break;
}
}
}// end of inner if
if(!AfxGetApp()->PreTranslateMessage(&msg))// 如果无法预处理消息
{
::TranslateMessage(&msg);// 转换消息
::DispatchMessage(&msg); // 发送消息
}
}
AfxGetApp()->OnIdle(0);
AfxGetApp()->OnIdle(1);
}// end of while
return TRUE;
}
[解决办法]
建议不要封装消息循环代码,而是按照实际需求来写,原因大概有几点:
1、消息循环的写法有很多种,而且作用范围不一样,很难做到完全兼容。
2、在消息进入窗口过程之前,很可能需要进行某些过滤,对话框通常有IsDialogMessage调用的要求,MFC有PreTranslateMessage的要求,WTL也有PreTranslateMessage的要求,有时可能也有TranslateAccelerator的要求,有些情况是不需要TranslateMessage的(当然写了也无妨)。
3、线程消息和窗口消息不是在所有情况下都等同对待的。
4、不是所有WM_DESTROY消息都需要调用PostQuitMessage的。
5、某些消息循环还需要等待同步信号,这种情况下GetMessage的调用就是不合适的。
另,比你的代码冗繁得多的消息循环代码多的是,不用担心这个。
[解决办法]
void CTestDlg::OnNcLButtonDown(UINT nHitTest, CPoint point) { m_bDig = TRUE; CDialog::OnNcLButtonDown(nHitTest,point); //新添加的代码}