MFC技术内幕

消息机制
   Windows程序的进行是依靠外部发生的事件来驱动,操作系统中有一个USER模块专门用来捕捉外围设备所发生的事件;比如当按下鼠标时,USER模块就捕捉到一个鼠标消息,而且依据当时系统界面的情况确定响应此消息的窗口,填充消息结构MSG,并将这个鼠标消息放入系统消息队列中,GetMessage函数从消息队列中取得一个消息,并依据消息的内容把消息发往特定的窗口函数,由窗口函数负责处理。每一条消息,都对应着一组代码段,程序通过执行代码段来完成我们的任务;在MFC中,用类的数据成员封装了我们要操作的数据,用函数成员封装了要执行的代码段;于是一条消息通常都对应一个函数。那么,消息怎么知道自己该由那一个类中的那一个函数成员来执行呢?
 
  首先,MFC为每一个能处理消息的类设计了一个消息映射表Message MAP,消息映射表负责把这个类能处理的消息和其处理函数
在一块。其次,把有继承关系的类的消息映射表链接起来形成一张消息网,通过依次比较有继承关系的各个类中映射表中的内容(MessageID)寻找与消息对应的处理函数,如果找到就调用其处理函数。如果在这张消息网中找不到相等的MessageID(网中的类中都没有定义响应这个消息的函数),即分两种情况处理:如果是命令消息或由其它控件发送过来的消息,就跳到另外一张消息网看看有没有符合的选择,跳完了专家们设定的该跳的网后仍然找不到符合的消息,则调用系统默认的处理消息的函数,找到了就调用其处理函数;如果是Windows消息,则不用跳了,调用系统默认处理函数就行了。由此可见,在消息传递的过程中,我们需要知道一些信息:这个消息是什么类型以及如果要跳网时应该先跳到那一张网,跳到那一张网后仍然找不到后才放弃。因此,在有处理消息能力的类的函数中定义了一个名为OnWndMsg函数分辨消息的类型,定义了一个名为OnCmdMsg函数来决定跳网的路线(这条路线由专家们事先设定好了)。

  把消息与其处理函数
在一块,把有继承关系的类的消息映射网链接起来,在MFC中是怎么办到的呢?MFC中设定了几个宏来负责有关工作:DECLARE_MESSAGE_MAP / BEGIN_MESSAGE_MAP / ON_COMMAND / END_MESSAGE_MAP。其中DECLARE_MESSAGE_MAP这个宏里主要包含了一个消息映射表结构成员,一个获取消息映射表结构地址的函数及一个messageEntris成员。而BEGIN_MESSAGE_MAP / ON_COMMAND / END_MESSAGE_MAP三个宏负责填充消息映射表的内容并依类的继承关系建立一张消息网。于是,当我们向类中加入一个新消息,我们就不必在类申明中加入任何的东西了,因为DECLARE_MESSAGE_MAP里有一个获取消息映射表结构地址的函数,我们就只需要向这个地址加入新的消息项和其处理函数名就行了。为类定义一个新消息就变成了做填空题。我们可以把这种消息与函数间的结构理解成一种模型;消息与函数之间原本应该直接对应的,现在我们为了方便管理方便操作,人为地把它们分开,加入中间层(消息映射表,专门管理消息与处理函数的对应关系),以达到更强大的功能。这是一模型,间接模型,也是一种方法,即把AC模型变成ABC模型。

动态生成与类型识别:
 无论是执行期类型识别,动态生成还是档案的读写,都是用同一数据结构CRuntimeClass同一张称为类别型录网的网。类别型录网是由CRuntimeClass链接而成的,在类中的声明由DECLARE_DYNAMIC宏封装,链接工作由类外的IMPLEMENT_DYNAMIC宏封装完成,当然根据不同的应用,CRuntimClass有不同的内容,所用的宏的名字也略有不同。其工作原理和消息机制有点相似,都是运用
指针这一大特性完成桥梁工作,也都利用指针在类外另构一张网,集中管理信息。这张网有什么大用途呢?是这样的,当我们在执行期要生成一个类对象时(比如在读档案时,里面的数据要根据实际情况产生相应的对象我们才能读),我们需要的信息:类的名字,类的大小,类的构造函数,类与其它类的关系等等有关类的信息,都将记录在类别型录网上;那么当我们在执行期获得一个(用字符串表示的)类名时,我们就可以在这张网上找出对应的元素(通过比较网中成员的类名),然后调用其构造函数(里面有个指针指向其构造函数),产生出对象。

  执行期所产生的对象相应的类必需要在类别型录网中才行,而这张网是由我们一手一脚用IMPLEMENT_DYNAMIC建立起来的,里面有些什么类,我们一清二楚。至于在如何建网,比较麻烦,反正有那两个宏自动帮我们完成这些工作,我们只需要做做填空题,确定把那些类挂在网上即可。大家回头想想,产生对象这件事,原本很简单的,原本我们可以直接产生的,可是为了把程序活跃起来,为了在执行期也能动态生成(那时我们可不能像以前那随随便便加个语句就生成一个对象了,因为我们不可能再加语句到已经分发的软件上去),于是我们加了个中间层,我们生成了一张网来集中管理类型信息,这种解决问题的办法很高明!把动态生成的过程也理解成一种模型,间接模型。

文档/视图结构
  我们把文档看成一种数据,而视图就是把这些数据按照我们想要的方式展示出来的窗口。如果一份数据只以一种方式显示,如果我们只需显示一种文件类型中的数据,那么,数据与视图一一对应,也不需要什么方法就能满足我们的要求的。可是更多的时候,我们需要把数据以不同的方式(比如有关统计的数据,我们期望有线形图,柱形图,文字等多种方式显示出来)显示出来,我们更希望在同一程序中能处理数种不同文件类型中的数据并为之提供不同的显示界面,那么一一对应好像就变得行不通了!怎么办?我们增加一个中间层,这个中间层在MFC中叫作Document Template,由它来负责集中管理文档视图之间的转换,应该说是管理Document/View/Frame,Frame是包在View外面的窗口,它可以为View/Document提供专用的菜单。为什么数据能以不多的形式显示?那是因为,据然数据能以一种形式显示,就必定能以多种形式显示。其实因为有了个中间层把文档视图分开,那么只要我们按原数据多设计几个显示形式就行了,我们需要什么形式显示,只要告诉Document Template,它就会体贴地帮我们安排好(接上我们想要的视图形式,和此视图专用的Frame)要做的工作了。

  同理,在同一主框架中为不同文件类型中的数据提供专用的View和Frame也由 Document Template这个中间层帮我们安排。在Document/View/Frame三位一体结构中,有一个链表把文件类型(一个Document Template对应管理一种类型)连接起来,在显示文件中数据时也有个查找过程,即先找到要显示的文件类型,再查找要显示View方式,之后动态生成专用的View/Frame。

Application Framework

  刚开始学VC时,就常听到有人说MFC就是类库,对API进行了简单的封装。果真如此吗?真是简单的封装吗?不!至少最重要最关键的几个类不是!MFC中几个最最重要的类,如CwinApp ,Cview , CframeWnd ,Cdocument ,CDocTemplate等;绝不仅仅是
简单的封装!它们之互相合作,通过消息的流动而沟通,并且互相调用对方的函数,等等,互相调用函数?说起来好像挺不错的,但做起来,要它们几个类在互相调用而显得乱七八糟的情况仍能条理清淅,共同完成几乎我们所开发的所有的程序的基本框架,

  Application Framework核心思想就基于面象对向开发程序的思想,为我们做出一套完美的基本程序模型,我们所开发的程序都以它为基础。在面象对向语言C++之下,我们只需要从模型中原有的类中派生出自己的类,改写一些虚函数,定义一些新函数,就可以方便地完成我们想要的功能了,很多麻烦的事(如处理Document/View/Frame中先前我们讨论的麻烦事,程序初始化等)都由基本程序模型帮我们解决掉了。


 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值