首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

关于自封装的消息循环函数的改进有关问题

2012-01-12 
关于自封装的消息循环函数的改进问题各位高手, 本人利用AfxBeginThread开辟了一个UI线程,并自写了一个消息

关于自封装的消息循环函数的改进问题
各位高手, 本人利用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的调用就是不合适的。

另,比你的代码冗繁得多的消息循环代码多的是,不用担心这个。
[解决办法]

探讨
如果不在PostNcDestroy内添加
delete this;

而用13楼的办法在最后退出的时候再销毁对象,
16楼的情况还是会发生……
在执行16楼的语句过程中,曾经弹出一个对话框:
The thread 0x418 has existed with code 0(0x0)
0x418 不是固定的,每调试一次都不一样。

我认为是问题的关键所在,不知各位高手有何看法?

[解决办法]
我感觉你的思维很乱,我觉得你应该找本mfc的书系统的看一下,重点搞清楚windows的消息机制,你对windows的消息机制还没搞清楚

不过我也解释不清楚你的问题

你的PreTranslateMessage函数处理鼠标左键,跟按键消息是没错

后来又,只是无法响应鼠标消息 
却可以相应 键盘消息…… 

这个确实不知道是什么情况,这个问题应该调试能很快找到原因吧

顺便问下你工作多长时间了?


[解决办法]
从消息循环上已经看不出有什么问题,估计与窗口的创建及消息响应有关,建议你另做一个简单的测试程序来分析这个问题。
[解决办法]
你的每个子窗体的确是在新的UI线程中的,这点没错。

1.主窗体无法响应鼠标消息是因为CtestDlg重载了OnNcLButtonDown函数,代码改成:
C/C++ code
void CTestDlg::OnNcLButtonDown(UINT nHitTest, CPoint point) {    m_bDig = TRUE;        CDialog::OnNcLButtonDown(nHitTest,point);   //新添加的代码} 

热点排行