PreTranslateMessage作用和用法

摘要:
传给PreTranslateMessage()的消息是未经翻译过的消息,它没有经过TranslateMessage()处理。PeekMessage和GetMessage的差别:GetMessage在没有消息的时候等待消息,cpu当然低PeekMessage没有消息的时候立马返回,所以cpu占用率高。由于游戏不能靠windows消息驱动,所以要用PeekMessage();PretranslateMessage的实现,不得不谈到MFC消息循环的实现。从接受到消息的窗体层层往上遍历,并调用PretranslateMessage看是否返回TRUE,是则结束,否则继续。[Page]假设用PostMessage,则消息进入消息队列,由GetMessage取得,PreTranslateMessage就有机会进行处理。

PreTranslateMessage作用和用法

PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的,绝大多数本窗体的消息都要通过这里,比較经常使用,当须要在MFC之前处理某些消息时,经常要在这里加入代码.

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

是否调用TranslateMessage()和DispatchMessage()是由一个名称为PreTranslateMessage()函数的返回值决定的,假设该函数返回TRUE,则不会把该消息分发给窗体函数处理。
传给PreTranslateMessage()的消息是未经翻译过的消息,它没有经过TranslateMessage()处理。能够在该函数中使用(pMsg->wParam==VK_RETURN)来拦截回车键。wParam中存放的是键盘上字符的虚拟码。

PeekMessage和GetMessage的差别:
GetMessage在没有消息的时候等待消息,cpu当然低
PeekMessage没有消息的时候立马返回,所以cpu占用率高。
由于游戏不能靠windows消息驱动,所以要用PeekMessage();
PretranslateMessage的实现,不得不谈到MFC消息循环的实现。MFC通过CWinApp类中的Pumpmessage函数实现消息循环,可是实际的消息循环代码位于CWinThread中,CWinApp仅仅是从CWinThread继承过来。其简化后的代码大概例如以下:
BOOLCWinThread::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));
}
returnTRUE;
}
能够看到,PumpMessage在实际的TranslateMessage和DispatchMessage发生之前会调用AfxPreTranslateMessage,AfxPreTranslateMessage又会调用CWnd::WalkPreTranslateTree(尽管也会调用其它函数,可是这个最为关键),其代码例如以下:
BOOLPASCALCWnd::WalkPreTranslateTree(HWNDhWndStop,MSG*pMsg)
{
ASSERT(hWndStop==NULL||::IsWindow(hWndStop));
ASSERT(pMsg!=NULL);
//walkfromthetargetwindowuptothehWndStopwindowchecking
//ifanywindowwantstotranslatethismessage
for(HWNDhWnd=pMsg->hwnd;hWnd!=NULL;hWnd=::GetParent(hWnd))
{
CWnd*pWnd=CWnd::FromHandlePermanent(hWnd);
if(pWnd!=NULL)
{
//targetwindowisaCwindow
if(pWnd->PreTranslateMessage(pMsg))
returnTRUE;//trappedbytargetwindow(eg:accelerators)
}
//gottohWndStopwindowwithoutinterest
if(hWnd==hWndStop)
break;
}
returnFALSE;//nospecialprocessing
}
能够看到,代码还是非常直接的。从接受到消息的窗体层层往上遍历,并调用PretranslateMessage看是否返回TRUE,是则结束,否则继续。
这里有一个地方非常关键:CWnd*pWnd=CWnd::FromHandlePermanent(hWnd)这一句代码从当前AfxModuleThreadState拿到Permanent句柄表,从而找到hWnd相应的CWnd
MFC中PreTranslateMessage是GetMessage(...)函数的下一级操作,即GetMessage(...)从消息队列中获取消息后,交由PreTranslateMessage()处理,若其返回FALSE则再交给TranslateMessage和DispatchMessage处理(进入WindowProc);
假设用SendMessage,则消息直接交到WindowProc处理,所以GetMessage不会取得SendMessage的消息,当然PreTranslateMessage也就不会被调用。 [Page]
假设用PostMessage,则消息进入消息队列,由GetMessage取得,PreTranslateMessage就有机会进行处理。
windows消息处理机制是这种:
首先系统(也就是windows)把来自硬件(鼠标,键盘等消息)和来自应用程序的消息 放到一个系统消息队列中去
.而应用程序须要有自己的消息队列,也就是线程消息队列,每个线程有自己的消息队列,对于多线程的应用程序就有和线程数目相等的线程消息队列.
windows
消息队列把得到的消息发送到线程消息队列,
线程消息队列每次取出一条消息发送到指定窗体,不断循环直到程序退出.这个循环就是靠消息环(while(GetMessage()) TranslateMessage();DispatchMessage();实现的.GetMessage()仅仅是从线程消息中取出一条消息,TranslateMessage()virtuekey消息转化成character消息,如VK_F1会转化成WM_HELP,DispatchMessage 则把取出的消息发送到目的窗体.假设收到WM_CLOSE消息则结束循环,发送postqiutmessage(0),处理WM_DESTROY销毁窗体!
while (GetMessage(&msg, NULL, 0, 0)) //C++ code
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

免责声明:文章转载自《PreTranslateMessage作用和用法》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇简单的ld链接脚本学习【赵强老师】Redis的RDB持久化下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

ACE_Task笔记

ACE_Task封装了任务,每个任务都含有一或多个线程,以及一个底层消息队列。各个任务通过这些消息队列进行通信。 其主要成员如下: open():初始化资源 close():释放资源 activate():启动线程,可指定线程的数目 svc():线程的启动位置 putq():放置消息到任务的消息队列中 getq():从任务的消息队列中取出消息 thr_co...

chrome性能指标(TTFB,TTSR,TTDC,TTFL)

1.TTFB (Time To First Byte) 是最初的网络请求被发起到从服务器接收到第一个字节这段时间,它包含了 TCP连接时间,发送HTTP请求时间和获得响应消息第一个字节的时间。 注意:网页重定向越多,TTFB越高,所以要减少重定向 TTFB优化的方法有:1.减少DNS查询2.使用CDN3.提早Flush4.添加周期头 2.TTSR(Tim...

RocketMQ入门介绍

  简介 用官方的话来说,RcoketMQ 是一款低延迟、高可靠、可伸缩、易于使用的消息中间件,具有以下特性(ps:对于这些特性描述,大家简单过一眼就即可,深入学习之后自然就明白了): 支持发布/订阅(Pub/Sub)和点对点(P2P)消息模型 在一个队列中可靠的先进先出(FIFO)和严格的顺序传递 支持拉(pull)和推(push)两种消息模式 单...

WCF学习笔记1(体系架构和行为扩展)

引用《WCF服务编程》里的一段话:“以WCF为基础框架搭建面向服务的企业级应用程序,以WF工作流引擎支撑企业应用中业务流程的传递与控制,以Cardspace和WCF固有的安全测罗保证企业信息的安全,最后以ASP.NET AJAX,WPF和SILVERLIGHT技术丰富客户端界面的绚丽表现,从而改善企业客户对应用程序的体验,这就是微软实现企业级应用的霸业宏图...

【WinForm程序】注册热键快捷键切换

重写DefWndProc事件 #region Window 消息捕获 const int WM_COPYDATA = 0x004A; public structCOPYDATASTRUCT { publicIntPtr dwData; public i...

C# Winform程序设计运行在高分屏下模糊解决办法

前段时间在开发一个坐标转换程序,开发环境是Windows10 64位专业版(V1803)和Visual Stuido 2015社区版,电脑屏幕是15.6英寸分辨率1920*1080,采用的是WinForm程序设计方法开发。在程序运行时遇到了这样一个问题,在Visual Studio设计的很清晰的菜单和界面,运行的时候菜单和控件上字体变得很模糊,界面大小也发...