了解一下下MFC---基础中的基础
(1)类CMYAPP
类CMYAPP是应用程序运行的基础,这个类是由MFC中的类CWINAPP派生来的。在这个类中除了有一般类都有的构造函数,一个重要的成员函数就是INITINSTANCE,我们知道,在Windows环境下面可以运行同一程序的多个实例,函数INITINSTANCE的作用就是在生成一个新的实例的时候,完成一些初始化的工作。
下面研究INITINSTANCE函数所做的事情,我们开始定义了一个文档模板对象指针PDOCTEMPLATE,通过NEW操作符,系统动态生成了这个文档模板对象,然后使用ADDDOCTEMPLATE函数把这个文档模板对象加入到应用程序所维护的文档模板链表当中,这个文档模板PDOCTEMPLATE的作用就是把程序用到的框架窗口,CMAINFRAME,文档CMYDOC,视窗CMYVIEW与应用对象CMYAPP联系起来。
CMYAPP类提供了用户与Windows应用程序之间进行交流的界面。在生成这个类的对象后,这个对象自动地把自身与Windows系统建立联系,接收Windows传送的消息,并交给程序中相应的对象去处理,这就免去了程序员许多的工作,使得开发C++的Windows程序变得简单方便。
(2)类CMAINFRAME
类CMAINFRAME是由MFC中的CFRAMEWND派生来的,所以它也是一个框架窗口。前面已经指出,CMAINFRAME是类CMYVIEW的父类,也就是说CMYVIEW类的对象显示在主框架窗口的客户区中。在类CMAINFRAME中,系统已经从类CFRAMEWND那里继承了处理窗口的一般事件的Windows消息,比如改变窗口的大小,窗口最小化等的成员函数,因此编程的时候程序员不需要再关心此类消息的处理,从而减轻了程序员的负担。当然,如果确实需要重新编写处理此类消息的成员函数,则需要对原有的成员函数进行重载。
在MFC程序中,我们并不需要经常对CMAINFRAME类进行操作,更多的是对视窗类进行操作,达到对程序中的数据进行编辑和修改的目的。
最后要指出的是,在MFC方式的程序中,当程序的一个实例被运行的时候,系统根据前面在CMYAPP类中介绍的文档模板对象自动生成类CMAINFRAME,CMYVIEW,CMYDOC的对象,而不需要程序员主动地去创建这些类的对象。
(3)类CMYVIEW与CMYDOC
之所以把CMYVIEW类和CMYDOC类放一起来介绍,是因为这两个类是密切相关的,文档是由文档模板对象生成的,并由应用程序对象管理,而用户则是通过与文档相联系的视窗对象来存储、管理应用程序的数据,用户与文档之间的交互则是通过与文档相关联的视窗对象来进行的。
生成一个新的文档的时候,MFC程序同时生成一个框架窗口,并且在框架窗口的客户区中生成一个视窗对象作为框架窗口的子窗口,这个子窗口以可视化的方式表现文档中的内容。视窗的重要功能就是负责处理用户的鼠标、键盘等操作,通过对视窗对象的处理达到处理文档对象的目的。
要指出的一点是,Windows应用程序分单文档界面SDI和多文档界面MDI两种,在单文档界面中,文档窗口与主框架窗口是同一概念。而这时的视窗对象则是显示在文档窗口的客户区当中。前面生成的test程序使用的就是单文档界面方式,此时文档窗口是主框架窗口,即类CMAINFRAME的对象。
文档/视图结构将数据操作和数据显示、用户界面分离开。这是一种“分而治之”的思想,这种思想使得模块划分更加合理、模块独立性更强,同时也简化了数据操作和数据显示、用户界面工作。文档只负责数据管理,不涉及用户界面;视图只负责数据输出与用户界面的交互,可以不考虑应用程序的数据是如何组织的,甚至当文档中的数据结构发生变化时也不必改动视图的代码。
MFC库消息映射
MFC库应用框架并没有采用虚函数来处理Windows消息,相反,它通过一些宏来将特定的消息映射到派生类中相应的成员函数。库类应用框架没有采用虚函数,这主要是因为以下原因:库类中包含了5个窗口类,分别和Windows的5种窗口类型相对应,如果采用虚函数的办法来处理消息,那么每个窗口基类就要对140条消息分别定义一个虚函数。C++对每个虚函数都要求有一个4字节的传递结构,称做“vtable”,无论该虚函数是否在派生类中被重新定义,“vtable”都必不可少。这样,对于每个特定类型的窗口或控件,应用都需要一个2.8KB大小的表来支持虚消息控制函数。
那么对于菜单命令消息及按钮命令消息来说,设计消息控制函数不能将它们定义成窗口基类中的虚函数,因为不同的应用会有不同的菜单项和按钮。MFC库的这种消息映射系统就避免了使用大的vtable表,并且能够处理各种各样应用的命令消息。这种体制也允许某些非窗口类(如文档类和应用类)来控制命令消息。这种消息映射体制同Borland作为OWL的一个组成部分所提供的“动态传递表”系统也有所不同,它不需要C++作任何扩展。
MFC库消息控制函数要求我们提供函数原型、函数体,以及在消息映射中的入口,而ClassWizard会帮助我们将消息控制函数引入我们所设计的类中,只要我们从列表框中选择一个Windows消息ID,ClassWizard就会自动产生具有正确参数及返回值的代码。