最后再介绍一下MFC类的分层结构,对于MFC分层结构的了解也是非常必要的。MFC的对象层次就好像目录结构的组织方式,它包含了一个跟对象CObject,其他大多数对象都是从CObject中直接或者间接派生出来的。CObject类提供了3个重要的特性:串行化支持、运行时类信息支持、诊断和调试支持。使用MFC开发应用程序会用到4个主要的类:CWinApp、CMainFrame、CMyView和CMyDoc。CWinApp类是应用程序运行的基础,CMainFrame类是一个框架窗口,CMyView类用于显示数据而数据的来源是CMyDoc类。MFC的基本类有三个:CObject、CCmeTarget和Cwnd,大多数MFC类都是由这三个基本类派生而成的。CObject类本身的功能很少,但是他为它的派生类提供了很多的基本功能;CCmeTarget类的派生类可以接受并且处理由菜单或工具栏发出的命令消息;CWnd类的成员函数封装了负责创建和文护窗口的Windows API。[ ]以上介绍的就是一些最主要的MFC类,MFC还提供了一些类来支持用户界面,例如:通用控件类、菜单类、对话框类、控件条类、属性类等等。
2.2 MFC中的消息映射机制
Windows程序和MFC程序是靠消息驱动的,他们对于消息的处理本质上是相同的。只是Windows程序对于消息处理的过程十分清晰明了,MFC程序则掩盖了消息处理的过程,以消息映射的方式呈现在开发者面前,使得开发消息的处理十分简单。[ ]用多了MFC就想对它的消息映射机制有一个本质的了解,下面将对消息映射做详细的分析。当然,在分析MFC消息映射之前首先对Windows程序的消息处理过程进行一个简单的描述。
2.2.1 Windows应用程序消息处理
Windows程序都文护有自己的消息队列,保存了队列消息(当然也有非队列消息,它们直接发给窗口),并用过消息循环对消息进行处理。消息循环首先通过GetMessage取得消息并从队列中移走,对于加速键会调用TranslateAccelerator函数,对其进行翻译和处理,如果处理成功就不在调用TranslateMessage。如果不是加速键,就进行消息的转换和派发,让目的窗口的窗口过程来处理消息。
真正处理消息的是所谓的窗口过程(LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)),这个函数的参数记录了过程对应的窗口、消息的ID以及参数,在其内部开发者可以实现自己需要的消息处理功能。窗口创建过程中有一个注册窗口类的步骤,消息是通过窗口类结构中回调函数指针指向名为WndProc的函数来发送给窗口的。
2.2.2 MFC消息映射
为了可以让消息更好的流动,MFC组建了一个很大的网,就是我们所说的消息映射图(Message map),它实现了消息所有可能的路线。MFC还实现了一个推动消息传动的引擎,让消息依照Framework的规划传递消息,这个引擎隐藏在各个类的虚函数中。
用三个宏连接完成消息映射。消息映射是MFC自带的消息传送机制,它是利用几个宏以及一定形式的表达方法,让Framework了解到该吧什么消息送到什么地方去。每一个类都最多拥有一个消息映射表格。这三个宏分别是BEGIN_MESSAGE_MAP、ON_COMMAND、END_MESSAGE_MAP。BEGIN_MESSAGE_MAP和END_MESSAGE_MAP一看就知道是一对宏,前一个作为开始有此消息映射表得类和它的父类两个参数,后一个作为结束的标志。中间的宏ON_COMMAND其实是一系列的宏,是指定命令消息的处理函数名称,除了ON_COMMAND还有很多其他的不同功能的宏也写在其他两个宏之间。有一些消息是标准的Windows消息,它们并不需要我们去指定消息的处理函数。例如宏ON_WM_PAINT,对应消息WM_PAINT,对应处理函数就是OnPaint()。
DECLARE_MESSAGE_MAP宏。消息映射它的本质就是一个很大的数据结构,用来为类似WM_PAINT这样的标准信息制定消息传输的路径,使它可以传输到父类那里去;也可以为WM_COMMAND这个特殊的消息制定消息传输的路径,使它能够传输到类层次结构的旁支去。DECLARE_MESSAGE_MAP中有两个不熟悉的类型AFX_MSGMAP_ENTRY和AFX_MSGMAP,前者是消息映射实体数组,最重要的任务就是让消息nMessage和函数pfn相应,pfn的数据类型AFX_PMSG被定义为一个函数指针,它记录了当前类的所有消息映射。每一个映射都由两方面组成:第一方面是关于消息ID的(前四个域),第二方面是消息对应的处理函数(后两个域)。后者AFX_MSGMAP是一个消息映射信息变量,它的功能是描述了当前类和基类的消息映射实体数组的入口地址。pBaseMap是基类消息映射入口地址,它提供了使消息可以在整个继承链表中传递的方法,很好的完成了消息映射的继承性。就是说,派生类即使没有设计处理一个消息的处理函数,但是其基类处理过这个消息,那么这个派生类也有处理这个消息的能力,当然派生类也可以用当前类消息映射入口地址lpEntries设计处理这个消息 MFC+socket无人驾驶汽车遥操作系统开发(3):http://www.751com.cn/jisuanji/lunwen_18916.html