PreTranslateMessage使用与使用说明 translatemessage

在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函数(前提是你有要保存这个对象的指针)。Ok。基本上就是这些。关于AfxThreadModuleState以及HandleMap我会写一些有关的文章,把这篇文章没有cover到的地方补齐。这是我的第一篇Blog,希望不要受到打击就好。BTW,其实我很讨厌MFC的,我更喜欢用API一些。以上出致:

http://www.winu.cn/space-14160-do-blog-id-5145.html

1. 函数原型(源自MSDN)

virtual BOOL PreTranslateMessage(MSG* pMsg);

功能:

重载该函数可以实现窗口消息在派发给窗口函数TranslateMessage()和DispatchMessage()之前的过滤.缺省的实现是完成加速键的翻译.因为您必须在你的重载版本中调用CWinApp:PreTranslateMessage()函数.

在MFC中,PreTranslateMessage()是虚函数,我们可以重载它来处理键盘和鼠标消息。

在SDK中,这又有所不同,我们必须在回调函数中

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)处理消息,它和PreTranslateMessage起的作用是类似的。只是MFC封装的更好而已。

2. 说明
PreTranslateMessage使用与使用说明 translatemessage

该函数表示在消息处理(TranslateMessage()和DispatchMessage()等)前所作的操作,如果函数返回值为TRUE,那么消息处理即终止,不会调用TranslateMessage()和DispatchMessage()来翻译和分发消息给相应的窗口;若返回值为FALSE,才会调用翻译和分发消息函数。

该函数是MFC消息控制流最具特色的地方,它是CWnd类的虚拟函数,通过重载这个函数,我们可以改变MFC的消息控制流程,甚至可以作一个全新的控制流出来。

在win32程序中,关于消息有两种传递方式:

a. MFC消息,MFC会把所有的消息一条条放到一个AFX_MSG_MAP_ENTRY结构中,形成一个数组,该数组存放了所有的消息和与它们相关的参数。也可以说是放到消息队列里去。

b.采用SendMessage()或其他类似的方式向窗口直接发送的而不经过消息队列的消息。

这两种方式中只有第一种(穿过消息队列的消息)才受PreTranslateMessage()影响,第二种消息并不会理睬PreTranslateMessage()的存在。

3. 其他

PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的,绝大多数本窗口的消息都要通过这里,比较常用,当你需要在MFC之前处理某些消息时,常常要在这里添加代码.

MFC消息控制流最具特色的地方是CWnd类的虚拟函数PreTranslateMessage(),通过重载这个函数,我们可以改变MFC的消息控制流程,甚至可以作一个全新的控制流出来。只有穿过消息队列的消息才受PreTranslateMessage()影响,采用SendMessage()或其他类似的方式向窗口直接发送的而不经过消息队列的消息根本不会理睬PreTranslateMessage()的存在。

一、是否调用TranslateMessage()和DispatchMessage()是由一个名称为PreTranslateMessage()函数的返回值决定的,如果该函数返回TRUE,则不会把该消息分发给窗口函数处理。

二、传给PreTranslateMessage()的消息是未经翻译过的消息,它没有经过TranslateMessage()处理。例如可以在该函数中使用(pMsg->wParam == VK_RETURN)来拦截回车键。

三、在WindowProc里不能处理WM_CHAR消息。(WindowProc函数见MFC消息响应机制一文)

四、SetWindowText会发送WM_CHAR给窗口。

五、PeekMessage和GetMessage的区别:

GetMessage在没有消息的时候等待消息,效率低。PeekMessage没有消息的时候立刻返回,所以CPU占用率高。因为游戏不能靠Windows消息驱动,所以要用PeekMessage();

在一个WIN32程序中,WINDOWS会将消息传递给相应的窗口。但是消息不是立即就被传递给相应的窗口,而是会从整个程序最顶层的窗口传递到下一级窗口,再传递到下一级窗口,直到传递给目标窗口。在整个过程中,有些消息,在某些特定的情况下,无法默认传递到目标窗口的。比如用户在EDIT控件中按下回车键,CANCEL键等,如果EDIT窗口之前有对话框窗口,对话框会默认处理回车消息(即响应ONOK函数,然后关闭对话框),然后退出消息传递。所以EDIT会收不到。要解决这个问题,可以在EDIT窗口之前所有的对话框中重载PreTranslateMessage函数,然后在函数内加上:

  if(pMsg->message==WM_KEYDOWN&&pMsg->wParam==VK_RETURN)//如果消息类型为WM_KEYDOWN并且用户按下的是回车

  returnFALSE;

  //不翻译消息,直接将消息传递下去。具体可查MSDN。注意,这里返回值不能为TRUE,TRUE的意思是翻译消息后退出消息传递,如此一来虽然也能避开对话框默认处理,但是会退出消息传递,这样EDIT控件照样得不到消息。(我一开始所犯的错误)



如此,就可避开对话框默认处理,将消息传递下去。注意:只有对话框才会默认处理按下回车,CANCEL消息,其他控件窗口则不会,所以在其他窗口中不必重载PreTranslateMessage函数,当然如果重载了也不会错。

附:关于PreTranslateMessage()函数的小程序示例:

  BOOLCUserDlg::PreTranslateMessage(MSG*pMsg)

  {

  if(pMsg->message==WM_KEYDOWN)//判断是否有按键按下

  {

  switch(pMsg->wParam)

  {

  caseVK_DOWN://表示是方向键中的向下的键

  //codehere

  break;

  caseVK_UP://表示是方向键中的向上的键

  //codehere

  break;

  default:

  break;

  }

  }

  }

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/mypwb/archive/2009/09/22/4577553.aspx

  

爱华网本文地址 » http://www.aihuau.com/a/25101014/194924.html

更多阅读

古剑奇谭破解补丁使用说明 古剑奇谭破解补丁

古剑奇谭破解补丁使用说明——简介《古剑奇谭》系列,是由GAMEBAR旗下上海烛龙研发的大型3D仙侠类角色扮演游戏。第一代作品《古剑奇谭:琴心剑魄今何在》已于2010年7月10日正式发行,为国内首部全程配音的单机游戏。古剑奇谭破解补丁已

痄腮散的使用说明 宝宝炸腮怎么办

腮腺炎,中医学称“痄腮”, 民间也称“猪头肥”。是儿童和青少年中常见的呼吸道传染病,由腮腺炎病毒所引起。冬春季节发病较多,病人是传染源,飞沫的吸入是主要传播途径,接触病人后2-3周发病。腮腺炎主要表现为一侧或两侧耳垂下肿大,肿大的腮

飞利浦电蒸锅使用说明 飞利浦温奶器使用说明

飞利浦电蒸锅使用说明——简介最自然温和的料理方法,保留食物的维生素和天然色泽,当然是蒸!飞利浦电蒸锅,在保留天然营养的基础上,让食物更加美味。现在就分享飞利浦电蒸锅的使用方法。很抱歉,视频数据暂时无法显示飞利浦电蒸锅使用说明

店铺包邮卡的使用说明 淘宝店铺设置包邮

买家可进入“我的拍拍=》我是买家=》我的优惠卡券=》我的包邮卡”中查看自己已经拥有的店铺包邮卡。使用说明:1、每一张包邮卡只能在所属的店铺内使用;2、使用包邮卡需满足使用规则(如单笔订单满100元)才能使用;3、有效日期内不限使用

惠普系统恢复使用说明 惠普电脑如何恢复系统

惠普系统恢复使用说明——简介现在预装系统的机器上大都集成安装了系统恢复功能,可以很方便的让我们在系统出现故障无法启动时,进行快速的系统恢复,同时系统恢复功能中还有文件备份,这样也保证了文件不丢失。惠普dv606b12TX,在开机时左下

声明:《PreTranslateMessage使用与使用说明 translatemessage》为网友壹眼萬年分享!如侵犯到您的合法权益请联系我们删除