- 浏览: 231200 次
- 性别:
- 来自: 广州
-
文章分类
最新评论
-
thebye85:
引用 另外一个需要注意的问题,就是SessionMap和隐藏对 ...
WebWork深度探索之Session -
lanxiaoshuang:
写的真好
说的都是概念——有关编程范式 -
lhz:
grep unique wc你需要的只是这么几个小工具而已
努力做个Pragmatic Programmer
我们都知道Windows应用程序是消息驱动(Message-Driven)的。而我们在编写应用程序的时候也是建立起消息映射表,并通过实现消息响应函数去处理用户操作产生的事件消息。关于消息驱动,有一个基本的概念要明确的,就是应用程序并不能直接得到来自用户操作的信息,而这些信息则是被操作系统拦截并封装成MSG类,然后再将信息发往相应的应用程序。
既然要发消息,那么就得先了解一下MSG的结构了。在WINUSER.H中,我们找到了MSG的定义:
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/dot.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](/Images/OutliningIndicators/None.gif)
在结构体tagMSG当中,hwnd是消息要发送到的窗口句柄(window handle);message是消息的标识符(message identifier),它是一个16位的无符号整数,用以表示消息的类型;而wParam和lParam则是消息本身的参数。
有了对消息的初步了解后,接下去需要了解的是消息的发送或者称为消息路由(Message Routing)。操作系统会有两种方式发送消息,一种是将消息放入消息队列中,另外一种就是直接将消息发往相应的应用程序。
首先分析第一种发送方式:操作系统维护着两种不同的消息队列:一个是系统消息队列,一个则是线程特定(thread-specific)消息队列(简称线程消息队列)。系统信息队列是各个GUI线程共享的,而线程特定信息队列则是每个GUI线程拥有一个。消息就由输入设备产生->系统消息队列->线程消息队列->相应的消息处理程序。而第二种方式则是越过了中间两个队列,直接传到了相应的消息处理程序。像窗口获得焦点(WM_SETFOCUS)这一类的信息都是以第二种方式发送的。
当消息发送至线程消息队列以后,任务的重点就转到消息处理程序上了。消息的处理通常都是通过消息循环来进行的。以下是很简单的消息循环的例子,源自MSDN:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/dot.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](/Images/OutliningIndicators/None.gif)
其中GetMessage方法的作用是从消息队列取得消息,并将消息复制到变量msg中,最后会将消息从队列中移走。GetMessage方法会有返回值,如果返回值为0(当取得的消息为WM_QUIT的时候),退出循环;如果返回值为-1,则说明取消息这一动作发生了异常,然后进行相应的处理;如果返回值为其他数值,则执行TranslateMessage和DispatchMessage方法。
而在MFC当中,我们可以从CWinThread的Run方法中找到MFC使用消息循环处理消息的过程:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/dot.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
从代码中,我们可以看到跟前面简单例子有两个不同的地方:第一是MFC使用了PeekMessage方法从消息队列中获得消息的方法,而不是直接使用GetMessage方法;第二就是使用了PumpMessage方法进行消息的处理。PeekMessage方法与GetMessage不同的地方就是:它从消息队列中得到消息,却不会将消息从队列中移走。使用PeekMessage方法也是因为它是一个具有异步行为的方法,如果消息队列中没有消息,它会立即返回,而GetMessage则不行,因为它的任务除了获得消息之外,还要从消息队列中将获得的消息移走,因此,一旦消息队列中没有消息,GetMessage方法就会被阻塞了,使得线程处于睡眠状态,这样就不会出现所谓的Idle状态,也就不会去执行OnIdle方法了。接下来,我们将注意力转到PumpMessage方法中:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/dot.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
![](/Images/dot.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
从代码中,我们可以知道,在PumpMessage方法中,通过调用GetMessage方法从消息队列中取走消息,然后根据其返回值来决定是否返回,这跟前面的简单例子是很类似的。如果GetMessage方法返回的是0或者-1都会返回FALSE,方法结束;如果返回的是其他正整数,那么将会执行最后的一个条件语句,在那里我们又见到了熟悉的TranslateMessage和DispatchMessage方法。通过这样一层一层的阅读源代码,我们可以发现MFC消息处理流程的主体与前面的简单例子是很类似的,只是增加了一些相应的扩展,使得消息的处理更灵活。
折腾了半天,终于对消息有了初步的了解。虽然MFC消息处理的流程并没有很特别的地方,但是其OnIdle方法以及PreTranslateMessage方法都是需要仔细研究的,让我们下次再续吧。
[1] MFC全接触(一)
发表评论
-
在String的面前丢脸
2004-06-18 00:39 1284重返C++的世 ... -
Summary of function parameter
2004-07-14 02:33 1174对C++这位入 ... -
此Vector非彼Vector
2004-08-05 15:51 1067在学习STL的过程中,我发现了一个熟悉的面孔— ... -
模板——泛型和STL的基础
2004-08-07 01:01 1347所谓泛型,从字面上可以猜想,就是泛化的类型(型 ... -
让人头痛的Vector(提问篇)
2004-08-07 16:55 1248在写完了此Vector非彼Vector这篇随笔 ... -
我该怎样shuffle呢
2004-08-10 01:47 1234在STL的Algorithm中有着这样的一种算 ... -
WebWork初体验
2004-08-11 17:43 1335在这篇ASP.NET ... -
WebWork深度探索之盲人摸象
2004-08-12 23:54 1174昨天尝试着利用WebWork做了一个小功能[1 ... -
WebWork深度探索之号外
2004-08-14 09:03 1069昨天开始对WebWork进行了一些初步的探索[ ... -
WebWork深度探索之标签库
2004-08-15 00:28 1545由于WebWork本身提供了一套自定义的标签库 ... -
什么是Law of Demeter
2004-08-15 14:22 1256今天一如昨日,继续对WebWork进行小打小闹 ... -
所谓的Dumb Question
2004-08-15 17:16 1054为了能够更 ... -
WebWork深度探索之标签库(续)
2004-08-16 15:58 1144昨日对WebWork的标签库进行了小小的研究[ ... -
WebWork深入探索之初见端倪
2004-08-19 16:35 935使用WebWork进 ... -
建网站的小Tips
2004-08-20 23:58 1049这几天都在忙着做一个小网站,从网页美工到后台处 ... -
URL与RequestDispatcher
2004-08-21 23:58 1014今天照例继续自己的网站建设之旅,原本以为可以大 ... -
WebWork深度探索之Pitfall
2004-08-25 14:31 991在使用WebWork进行开发的过程中,她的种种 ... -
WebWork深度探索之Session
2004-08-26 15:38 1534昨天上午刚 ... -
搞笑的textarea标签
2004-08-31 18:17 1593很久没有用 ... -
两天四疑问
2004-09-03 10:56 10179月份的前两天,我仍然做着网站开发的工作。在开 ...
相关推荐
C语言库函数,C++库函数,C++教程,the C++ primer plus,the C++ standard library,MFC深入浅出,WIN32API大全,Effective C++ 2rd edition,汇编语言全接触.chm,win2000api.exe,Win32 APIfor Visual Basic 大全.chm,...
卷 data 的文件夹 PATH 列表 卷序列号为 64ED-8C1D D:\我的酷盘\FTP\学员面试资料 │ 164个完整Java代码.zip │ J2EE综合--Struts常见错误的全面汇总.txt │ java程序员面试资料.zip │ JAVA笔试题(上海释锐)....
卷 data 的文件夹 PATH 列表 卷序列号为 64ED-8C1D D:\我的酷盘\FTP\学员面试资料 │ 164个完整Java代码.zip │ J2EE综合--Struts常见错误的全面汇总.txt │ java程序员面试资料.zip │ JAVA笔试题(上海释锐)....
卷 data 的文件夹 PATH 列表 卷序列号为 64ED-8C1D D:\我的酷盘\FTP\学员面试资料 │ 164个完整Java代码.zip │ J2EE综合--Struts常见错误的全面汇总.txt │ java程序员面试资料.zip │ JAVA笔试题(上海释锐)....
卷 data 的文件夹 PATH 列表 卷序列号为 64ED-8C1D D:\我的酷盘\FTP\学员面试资料 │ 164个完整Java代码.zip │ J2EE综合--Struts常见错误的全面汇总.txt │ java程序员面试资料.zip │ JAVA笔试题(上海释锐)....
卷 data 的文件夹 PATH 列表 卷序列号为 64ED-8C1D D:\我的酷盘\FTP\学员面试资料 │ 164个完整Java代码.zip │ J2EE综合--Struts常见错误的全面汇总.txt │ java程序员面试资料.zip │ JAVA笔试题(上海释锐)....