• ----:)欢迎访问源码网(:----
    • 首页
    • 博客
    • 学院
    • 下载
    • 论坛
    • 影视
    • 发布源码
    • RSS
    • ITPig
    • 笑话网
    • 百家姓
    • 繁體中文

源码网 - 中国第一源码门户
选择镜像:网通镜像 - 电信主站
  • 首 页
  • 新闻动态
  • 网站运营
  • 网页制作
  • WEB开发
  • 编程开发
  • 图像媒体
  • 操作系统
  • 数据库
  • 服务器
热门搜索 优化 SEO 故事 cms IIS7 MySQL 个人 AdSense 主题推广 | 文章搜索: 高级搜索
会员登录/控制面版您的位置: 学院首页 >> 编程开发 >> 汇编语言 >> 详细内容
 

推荐文章

 
 

热点文章

  • API Hook完全手册
  • MFC的模块状态:从AfxGetApp()和AFX_MANAGE_STATE()看..
  • 如何在程序启动的时候自动挂接Debugger
  • MFC中PretranslateMessage的实现
  • COM对象创建过程总结(进程外和进程内)
 
 

相关文章

  • MFC的模块状态:从AfxGetApp()和AFX_MANAGE_STATE()看..
 
 

百度搜索

 
 

MFC中PretranslateMessage的实现

  • 阅览次数:
  • 文章来源: http://blog.csdn.net/ATField/archive/2007/02/15/1510800.aspx
  • 原文作者:
  • 整理日期: 2008-07-17
  • 发表评论
  • 字体大小:
  • 小
  • 中
  • 大

在MFC里面,PretranslateMessage是一个很重要的虚函数。这个函数的作用这里就不谈了,很多地方都有涉及,这里只谈一下其实现的机制。
谈到PretranslateMessage的实现,便不得不谈到MFC消息循环的实现。MFC通过CWinApp类中的Pumpmessage函数实现消息循环,但是实际的消息循环代码位于CWinThread中,CWinApp只是从CWinThread继承过来。其简化后的代码大概如下:

BOOL CWinThread::PumpMessage()
...{
    _AFX_THREAD_STATE 
*pState = AfxGetThreadState();

    ::GetMessage(
&(pState->m_msgCur), NULL, NULL, NULL))
 
    
if (!AfxPreTranslateMessage(&(pState->m_msgCur)))
    
...{
        ::TranslateMessage(
&(pState->m_msgCur));
        ::DispatchMessage(
&(pState->m_msgCur));
    }

    
return TRUE;
}

可以看到,PumpMessage在实际的TranslateMessage和DispatchMessage发生之前会调用AfxPreTranslateMessage,AfxPreTranslateMessage又会调用CWnd::WalkPreTranslateTree(虽然也会调用其他函数,但是这个最为关键),其代码如下:

BOOL PASCAL CWnd::WalkPreTranslateTree(HWND hWndStop, MSG* pMsg)
...{
    ASSERT(hWndStop 
== NULL || ::IsWindow(hWndStop));
    ASSERT(pMsg 
!= NULL);

    
// walk from the target window up to the hWndStop window checking
    
//  if any window wants to translate this message

    
for (HWND hWnd = pMsg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd))
    
...{
        CWnd
* pWnd = CWnd::FromHandlePermanent(hWnd);
        
if (pWnd != NULL)
        
...{
            
// target window is a C++ window
            if (pWnd->PreTranslateMessage(pMsg))
                
return TRUE; // trapped by target window (eg: accelerators)
        }

    
        
// got to hWndStop window without interest
        if (hWnd == hWndStop)
            
break;
    }

    
return FALSE;       // no special processing
}

可以看到,代码还是很直接的。从接受到消息的窗口层层往上遍历,并调用PretranslateMessage看是否返回TRUE,是则结束,否则继续。
这里有一个地方非常关键:CWnd *pWnd = CWnd::FromHandlePermanent(hWnd) 这一句代码从当前AfxModuleThreadState拿到Permanent句柄表,从而找到hWnd对应的CWnd对象。关于PreTranslateMessage有一个常见的问题就是与此有关:如果编写了一个MFC DLL并从另外的一个MFC主工程之中调用这个MFC DLL中的Modeless Dialog的话,Modeless Dialog的PreTranslateMessage不会被调。因为MFC DLL和这个MFC工程拥有不同的AfxModuleThreadState,因此在MFC DLL中创建的modeless CDialog对象不在MFC工程的句柄表中(CWnd::FromhandlePermanent返回NULL),因此虽然MFC主工程中的CWinApp的Pretranslatemessage会被调(注意此时Dialog的消息循环在MFC主工程里面),但是不会调用MFC DLL中创建的那个modeless CDialog的PreTranslateMessage函数。因此需要特殊处理。一般有两种方法:
一种是直接在MFC主工程中的CWinApp::PreTranslatemessage里面调用MFC DLL的CWinApp::PreTranslateMessage(可以专门在MFC DLL中export一个专门的函数来做这件事情)。另外的方法是使用钩子,在钩子消息处理函数之中,判断目标窗口是否是当前具有焦点的窗口,如果是,则直接调用目标窗口的PreTranslateMessage函数(前提是你有要保存这个对象的指针)。

上一篇:PHP使用zlib扩展实现页面GZIP压缩输出
下一篇:构建支持Master/Slave读写分离的数据库操作类
  • 网友评论:
  • 查看所有评论
  • 我要发表评论
您的网名:
留言主题:
你要发表的内容:

 

关于本站 | 广告联系 | 版权声明 | 网站地图 | 发布软件 | 帮助中心 | 源码论坛

Copyright © 2005-2007 CodePub.Com  程序支持:木翼  滇ICP备05005971号