MFC文档视图(一):简介

来源:互联网 发布:体细胞重编程研究进展 编辑:程序博客网 时间:2024/05/16 04:36

刚一接触MFC还真有点让人不所措,不知道如何下手.用向导生成一个简单的SDI项目,自动生成一堆代码.看着有点云里雾里的.这主要有下面一些让人晕乎的地方.

1.不容易理解程序的入口点.学C的话看代码都是先找着main函数,然后顺着往下看.就像个树形结构,main函数是根结点.这样看起来条理清晰,一目了然.C#虽然是纯面向对象,它好好歹还是把main函数封装在一个类中.

2.很多类看不到在哪里实例化了就被拿来用了.因为只定义一个类放那里是一个死家伙,除了可以直接调用它的静态变量和函数外是没法用的.只有实例化成一个对象时才能调用.

3.一些类之间的关系太复杂.说到面向对象我们容易想当然的想到设计的最基本单元是类,实际上不全对.只有那些比较独立的类,没有调用到其他类.就可以看成一个单元.而很多类相互关联(一般就是某些变量成员是其他类对象,也就是通常说的has-a关系).这样你必须把几个相关的类结合起来当作一个单元看才能理解,光独立的看一个无法理清头绪.

4.消息的的处理.在C中处理windows消息时,直接一个while循环,然后一路case下去,随便指定一个函数去处理某种消息就行.而MFC中只有继承于某些类的类才能处理某类消息.

 

先把用向导生成的SDI项目中自动添加的类拿来瞧瞧,然后分析下看.再慢慢回答上面4个问题.

自动生成的类有4个,彻底理解了这4个类就能想明白上面的难点了.这4个类是相互联系的一个单元,必须联系起来分析.这4个类是.

CMyWinApp , CMyDoc, CMyFrameWnd, CMyView. 当然这名字是随便取了.关键是它们要分别继承于MFC类库中的下面4个类

 

CWinApp , CDocument, CFrameWnd, CView. //4个关键类这是人家微软给你做好的类.你只要建个类继承它们,然后添加些东东就可以用了.

 

4个关键的类

猜想下4个类干嘛的

上面的4个类具体干嘛的呢.我们可以顾名思义的猜想下.第一个字母C是所以MFC类中都有的,所以不用管了.

CWinApp  //应用是windows application的简称吧,应用程序,那应该是程序运行的入口点

CDocument //document是文档的意思,那应该是处理数据的类吧

CFrameWnd //这应该是frame window的简称.框架窗口,应该跟窗口也就是UI界面相关的.想象下相框的外面的框架

CView //view视图,应该也是跟UI界面相关,想象下相框除了外面框架的相片本身.(相片还可以取出来放另外一个框架上去)

 

项目中分别继承上面4个类的类是对应4个c++源文件.很容易就瞧出来.不过在CMyWinApp类中有个函数中还有用到一个类CSingleDocTemplate实例化的对象.一般叫文档模板类.注意这里的模样可跟泛型编程中的模板没一点关系.因为上面说的4个类是互相联系的嘛.所以这个类主要是协调管理其他类之间的关系.

 

5个类与MVC关系

我们知道一个应用程序可以分成两大块,一块是是数据处理,一大块是数据显示(也就是UI界面).那CDocument主要是处理数据,CFrameWnd和CView主要是UI界面的显示.而CSingleDocTemplate就是管理数据和UI界面之间的逻辑联系了.看到这里你是不是觉得这有点像传说中的MVC (model-view-controller)模式了.其中CDocument自然对应model层,CFrameWnd和CView对应viewn层,而CSingleDocTemplate对应controller层.不过这只是个简化的MVC,controller这一层没做太多事,所以实际上主要是两层了model-view.

 

5个类的继承层次关系(下面的类都是MFC类库中的)

CObject (mfc框架中所有类都继承自它)

  (1)CCmdTarget

         (1.1)CWinThread

               (1.1.1)CWinApp

         (1.2)CWnd

               (1.2.1)CFrameWnd

               (1.2.2)CView

         (1.3)CDocument

         (1.4)CDocumentTemplate

               (1.4.1)CSingleDocTemplate

        

 

程序的入口与4个类的实例化

MFC背后的详细流程候捷的<深入浅出MFC>中有解释.不过由于太详细,细节太多,刚开始看可能看的一头雾水.这里就简化的讲下.

首先是MFC中了有main函数的,毫无疑问main函数是入口点.不过不把它隐藏了,只有编译的时候把它嵌进去.

上面说的4个类我们只看到CMyWinApp有实例化,其他3个类是被做为变量成员实例化.而那些变量成员是在这其他类的父类中.CMyWinApp是做为一个全局变量被实例化,所以它是先于main函数之前执行.由于main函数隐藏了,所以把CMyWinApp当作程序的入口点就行.当CMyWinApp实例化后(假如为app)接着main函数执行,它于是调用app的一些函数,这些函数再一路调用下去(有些地方就会实例化其他3个类).当然你肯定会问main函数怎么知道来调用你定义的类中的函数啊.这就是多态了.main函数中只要用一个指针指向CMyWinApp的父类,然后调用一个虚函数,这里我们只关注InitInstance()这个虚函数,因为代码中只能看到它.其他的就不管了.而CMyWinApp有重写这虚函数(它其实只是添加一些操作,这函数里还有调用CWinApp.InitInstance()) 于是main函数就调用重写的函数了.

实际上你可以看在VS中设些断点,然后按F5不断的debug,就会发现那些类的构造函数不停的被调用到,自然是实例化时才调用构造函数.实例化的顺序是这样的.

程序执行顺序

1.CMyWinApp(实例化,调用构造函数) -- >

2.main函数执行,并调用CMyWinApp中的函数InitInstance-->

3.InitInstance函数执行,函数中有实例化类CSingleDocTemplate,并且有传3个类为参数,分别是CMyDocument, CMyFrameWnd, CMyView. -->

4.CSingleDocTemplate类中某个地方实例化CMyDocument,CMyFrameWnd.-->

5.CMyFrameWnd(实际上是它父亲)某个地方实例化CMyView.

.

 

简单的基于对话框的项目

上面讲的是SDI项目,复杂很多.而基于对话框的项目简单很多.执行顺序如下

1.CMyWinApp(实例化,调用构造函数) -- >

2.main函数执行,并调用CMyWinApp中的函数InitInstance-->

3.InitInstance函数中实例化类CMyDlg,该类继承自CDialog,而CDialog又继承自CWnd.这里没有啥文档类,视图类,框架视图类了.就一个CDialog,它就是一个图形界面.

所以这里就没有涉及到类似MVC的东东把数据处理和UI界面分开.就直接数据和UI混到一起处理了.