MFC消息截获之pretranslatemessage

来源:互联网 发布:js json对象 编辑:程序博客网 时间:2024/04/29 15:12

前几天,查了一个batch的问题,问题大致是这样,父窗口消息一个鼠标消息,弹出一个模态框,CPU负荷就飚升到100%(双核就是50%),非常怪异,用windbg,分析哪个线程占用CPU,定位到鼠标响应函数,也就是弹出模态框的函数,windbg提供的信息有限,只能自己分析,经过各种尝试,发现与模态框里面的控件无关,所以应该还是父窗口的问题,仔细看了下父窗口的代码,发现父窗口为了截获F1按下的消息,而重载了Pretranslatemessage,而Pretranslatemessage返回值都是真!!就是这个返回值导致的,下面我们来分析下,为什么影响这么大:

以模态对话框作说明
[code]
MyDiag test = new MyDiag(NULL); 
test.DoModal();
[/code]
我们重点看DoModal后面windows做了什么,简单来说应该做了两件事:
1)发送一个DlgInit消息,这个消息最终的响应就是对话框的OnInitDialog(),创建成功后返回窗口句柄
如果DoModal后窗口还没显示出来就崩溃或者assert,OnInitDialog里面的代码怀疑最大,可能里面某些控件有问题,譬如没有注册,找不到等
2)进入消息循环,窗口就可以消息处理各种消息响应了
消息循环的关键代码如下:
[code]
do 

   if ( !PreTranslateMessage(&msg)) 
    { 
      ::TranslateMessage(&msg); 
      ::DispatchMessage(&msg); 
    } 
}while(::PeekMessage(pMsg,NULL,NULL,NULL,PM_NOREMOVE));
[/code]
从2的代码中我们可以看到,如果PreTranslateMessage为真,那就进入不会进TranslateMessage,跟不用说是消息的分发与响应了,这也就是为什么可以通过重写PreTranslateMessage可以消息队列中的消息,甚至是重定向消息,
PreTranslateMessage为真后,这个消息循环就空转,像一个死循环,为什么说像,而不是是,是因为windows会处理是不是idle的情况,当创建一个模态框后,焦点转到模态框,父窗口这是应该无法处理到idle的情况,而进入死循环,导致负荷一下飚升到50%(双核),修改PreTranslateMessage,出了要截获的消息,其他消息返回假,让消息循环继续处理消息。

0 0