2024年4月11日发(作者:)

1.1 MFC 文档视图结构程序结构总揽

当我们使用 MFC AppWizard 生成一个 MFC 程序,选用所有默认的设置

(当然也是 Multiple Documents ,本文讨论主要基于 Multiple Documents ,

对于 Single Document 情况仅以简单表述提及,皆因后者和前者很多相似相同

之处,但前者更为复杂,并且更加常用。),假设你的程序名称为 A ,则你会

得到 CMainFrame 、 CChildFrame 、 CAboutDlg 、 CADoc 、 CAView 、

CAApp 6 个类( Single Document 仅少一个 CChildFrame 类,其余均同)。

这些类的具体含义将在后面给出,这里先要给出一个 MFC 支持文档视图结构

程序(以下简称 App )的主要组成:

一个 App (对应类 CAApp )可以包含多个文档模版( CDocTemplate ),

但是 MFC AppWizard (无论是 SDI 还是 MDI )都只是默认生成一个。但是

在实际开发中一个文档模版不够,需要自己手工添加(在后面实际项目例子提供

示例)。这个结构是通过 MFC 中 CWinApp 的成员变量 CDocManager*

m_pDocManager 实现的,我们的 CAApp 正是继承自 MFC 提供的

CWinApp 类。

CDocManager 类则拥有一个指针链表 CPtrList m_templateList 来维护这

些文档模版。这些文档模版都是在 CAApp :: InitInstance ()中通过

AddDocTemplate(pDocTemplate) 。

CDocTemplate 拥有 3 个成员变量,分别保存着 Document 、 View 、

Frame 的 CRuntimeClass 指针,另外持有成员变量 m_nIDResource ,用来

指定这个 Document 显示时候采用的菜单资源。这 4 份数据都在 CAApp ::

InitInstance ()中 CDocTemplate 的构造函数中指定。在 Document 中拥有

一个回指 CDocTemplate 的指针( m_pDocTemplate )。

一个文档可以有多个视图,由 Document 中成员变量 CPtrList m_ViewList

维护。

CFrameWnd 拥有一个成员变量 CView* m_pActiveView 指向当前活动的

View 。

CView 中拥有一个成员变量 CDocument* m_pDocument 指向该视图相

关的 Document 。

[ 注解 ] : ① MFC SDI/MDI 程序默认都默认生成了一个文档模版,并将

这个文档模版 Add 到其文档模版的链表中,由于这是 MFC 默认提供的,因此

这个文档模版会被插入到文档模版的第一个位置,而 MFC 也是通过这个文档

模版的特定位置可以确定的。默认情况下,当我们点击 File ( Open ) / File

( New )的时候,这个文档模版会被启用。

除了侯捷先生在《深入浅出 MFC 中列出的以上的深入分析,我们还应该

(很大程度上更加重要)掌握以下的关于 MFC SDI/MDI 的知识:

文档的本质:文档是用来保存数据以及关于数据的处理的,每当 MFC

SDI/MDI 响应 File ( Open ) / File ( New )的时候都会打开一份文档。

文档可以拥有多个视图。文档和视图的关系可以这样理解:文档是被视图观察的

对象。

视图本质:视图在 Windows 中就是一个窗口,也就是一个可视化的矩形区

域。视图是用来表示文档的数据的。但是每个视图必需依附于一个框架( SDI 中

是 MainFrame , MDI 是 ChildFrame )。当然你可以自己去 Create 一个视

图,并且去显示它。

框架的本质:框架实际是也是一个 Windows 窗口。但是在框架上可以放置

菜单、工具栏、状态栏等。而视图则放在框架的客户区。因此 MFC 中我们看

到的窗口实际上 Frame 和 View 共同作用的结果。

在某一时刻,程序中只有一个活动的文档、框架和视图,即当前的文档、框

架、视图。

1.2 MFC SDI/MDI 各个类之间的互访

在实际项目开发中用的最多就是各个类之间的互访问,这里将网络上和书籍

中提到的做了一个总结,也是笔者在实际开发中都用到过的。

访问对象

应用程序 App

访问位置

任何位置

访问实现

① AfxGetApp();

② 在要使用应用程序 App 的文件

中加入:

extern CAApp theApp ,然后直接

使用全局的 theApp 变量。

① AfxGetMainWnd();

② AfxGetApp()->m_pMainWnd;

GetActiveView();// 当前的活动视图

GetFirstViewPosition (); // 可以

获取全部视图

GetNextView ();

GetDocument() ;

GetFirstDocPosition(); // 该文档模

版对应全部文档

GetNextDoc();

GetActiveDocument(); // 当前活动

文当

主框架窗口

任何位置

视图

框架类中

文档类中

文档

文档类中

文当模版类

框架类中