CDocument

来源:互联网 发布:在线作诗软件生成器 编辑:程序博客网 时间:2024/04/30 17:06
 CDocument类为用户定义的文档类提供了基本的函数功能。文档类表示了通常用于File Open命令打开和使用File Save命令保存的数据。
  CDocument支持标准操作,如创建、装载、保存等。框架用CDocument定义的界面来操作文档。
  应用可支持多种文档,例如文本文档和工作表。每种类型都有一个相关的文档模板。文档模板指定该类文档所使用的资源(如菜单、图标和加速符号表)。每个文档还含有一个CDocTemplate对象指针。
  用户通过与文档相联系的CView对象来与之交互。视图在框架窗口内生成一个文档图象,并解释作用于该文档之上的用户输入。一份文档可以有多个相关的视图,当用户在文档上打开一个窗口时,框架创建一个视图并将其与文档连接。文档模板为每类文档指定了用于显示的视图类型和框架窗口。
  文档作为窗口标准命令例程的一部分,接收标准用户界面组件(如FileSave菜单项)的命令。文档在活动视图之后接收命令。如果文档未能处理指定的命令,则将其交给管理它的文档模板。
  当文档数据被修改时,各个视图都必须反应这些修改。CDocument提供了UpdateAllViews成员函数为视图通知这些变化。框架在关闭之前会提示用户必须存储修改后的文件。
  在一个典型的应用中生成一个文档,必须做到以下几点:
  ·为每种类型的文档从CDocument中派生一个类。
  ·添加保存在文档数据的成员变量。
  ·为阅读和修改文档数据提供成员函数,文档的视图是这些成员函数最重要的用户。
  ·在文档类中覆盖CObject::Serialize成员函数,从磁盘读取文档数据或将其写入磁盘。
  CDocument支持通过邮件发送文档,如果存在邮件支持(MAPI)的话。

  所需头文件:#include <afxwin.h>

MFC之所以能成为application framework,很大的原因就在于其Document/View结构对于快速开发的支持。Document/View很好地划分了程序代码的前台后 台,让程序员可以专心于设计数据结构和UI。
Document即为“资料”,按我理解就是饭店的厨师;而View就是饭店的服务员。View负责点菜和上菜(对用户请求做出直接响应),而 Document负责烹饪,即处理用户的要求。
除了Document和View,还有一个Frame,因为View要放在Frame内部,Frame就是承载View的框架。而三者之间的关系是由 Document Template来管理的,一份Document Template管理一个document\frame\view三件组,而一个程序可以有多个document template,多个document template由一个CDocManager对象管理。

document template

一个MDI(多文档接口)应用程序使用主框架窗口(main frame window)作为工作区,在工作区里用户可以打开多个文档框架窗口,每一个文档框架窗口用以显示一份文档。

Document template是用来定义以下三种类之间关系的模板:

Document(文档)类,从CDocument派生而来,用于处理数据,即所谓数据之体。

View(视图)类,用于将来自Document类的数据显示出来,可以从CView、CScrollView、CFormView和 CEditView类派生,也可以直接使用CEditView类。

框架窗口(frame window)类,用以包含View。对于MDI程序,可以从CMDIChildWnd派生,也可以直接使用该类。

MDI应用程序可以支持不止一种文档,而且不同种类的文档可以同时打开(比如一个text和一个bitmap)。对于每一种所支持的文档,应用程序 都应该有一份对应的document template进行管理。也就是说你的应用程序支持几种文档,就应该有几个Document template。

当用户创建新文档的时候,应用程序就会使用document template。如果程序支持的文档种类在一种以上,那么程序框架就会从document templates处取得所有的文档类型名字,显示在File New对话框里。一旦用户选择了文档类型,应用程序就会创建一个document对象,一个frame window对象和一个view对象,并且将它们联系在一起(通过document template)。

通常程序员不需要使用CMultiDocTemplate的任何成员函数(除了构造函数外)。框架会在内部自动处理 CMultiDocTemplate对象。

为了管理通过相关view对象和frame window对象来构建document的复杂过程,framework使用两种document template类:
CSingleDocTemplate类用于SDI程序;CMultiDocTemplate类用于MDI程序。一个 CSingleDocTemplate在同一时刻只能创建并储存单一种类的一个文档;一个CMultiDocTemplate在同一时刻可以管理单一种类 的多个文档。

有些应用程序支持不止一种文档类型,比如同时支持文本和图形。这种应用程序为每个支持的类型使用单独的document template对象,见下图:

这个应用程序支持两种文档类型,因此具备两个document template对象。对于每一种文档类型可以打开多个文档,每打开一个文档应用程序就为之创建三个对象:CMyDocument对象用于处理数 据,CMyView对象用于显示,CMyFrameWnd用于装载view,但是不管打开多少个同类型文档,负责管理该类型的document template对象只有一个,它负责管理的是上述三个类之间的关系,负责在这三个类的对象创建之时指定它们之间的关系。

上面说到每打开一个document,会随之一起创建一个view和一个frame window,而这三者的创建工作就是由document template完成的,当用户点击“File/New”或者“File/Open”后,消息发出,被theApp的OnFileNew()接到,但它经 过一系列的调用(比较绕)最终调用的是CMultiDocTemplate::OpenDocumentFile(),该函数完成此三对象的创建,其中 view的创建又是非常的绕,最终经过一系列的调用由CFrameWnd::CreateView()完成,另外还会调用CView从CWnd继承来的函 数Create()用于产生与该view对应的真实窗口。而创建什么种类的document、window、view是在创建document template时由document template的构造函数的参数指定的。下面显示了创建一个CMultiDocTemplate(用以管理MDI的document template)的过程:

CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(IDR_CMyDocTypeTYPE,
?? RUNTIME_CLASS(CMyDoc),
?? RUNTIME_CLASS(CChildFrame), // custom MDI child frame
?? RUNTIME_CLASS(CMyView));
if (!pDocTemplate)
?? return FALSE;
AddDocTemplate(pDocTemplate);

传给构造函数的第一个参数是一个资源ID,该资源用于提供该文档类型的菜单、快捷键、按钮等。剩余三个参数用RUN_CLASS()宏提供 CMultiDocTemplate创建document\window\view时所需要的类型信息(即对应的RuntimeClass对象,当用户打 开一个文件时,document template就可以据此动态创建出document\window\view,这就很好体现了MFC动态创建的用途,关于动态创建是由 DECLARE_DYNCREATE()\IMPLEMENT_DYNCREATE()宏实现的),最后用AddDocTemplate()加载此 document template,AddDocTemplate()实际上是将document template加到由theApp的一个指针CDocManager* m_pDocManager所维护的document template链表中CDocTemplate有三个成员变量分别持有document\window\view的RuntimeClass对象的指 针,另外还有一个资源ID成员。

Document template对象是被theApp创建的。在theApp的InitInstance()中的一个关键任务就是创建一个或多个适当种类的 document template。theApp会在template list中保存指向每一个document template的指针并提供一个接口用于增加document template(AddDocTemplate())。如果你想要支持两个或以上的文档类型,你必须为每个文档类型显式地调用 AddDocTemplate()。

多个Document template是由一个CDocManager对象管理的,很多原本由CWinApp做的关于document template的工作如:AddDocTemplate()、OpenDocumentFile()、NewDocumentFile(),在 MFC4.0后都由CDocManager来做了。

CDocTemplate\CDocment\CFrameWnd \CView之间的指针互指关系
列出:

CDocTemplate有指向其余三者RuntimeClass对象的指针:
?CRuntimeClass* m_pDocClass;
?CRuntimeClass* m_pFrameClass;
?CRuntimeClass* m_pViewClass;
还有指向Document列表的指针:CPtrList m_pDocList;表示一个CDocTemplate可以维护多个同类型文档。

CDocument有CDocTemplate* m_pDocTemplate回指CDocTemplate;另有CPtrList m_pViewList指向一个view的链表,表示一个Document可以对应多个View。

CFrameWnd有CView* m_pViewActive指向当前活动在其中的view。

CView有CDocument* m_pDocument指向对应的Document。

CDocument\CFrameWnd\CView之间互相操作的 函数

CDocument::UpdateAllViews()—————>CView:OnUpdate()
CView::GetDocument();
CView::GetParentFrame();
CFrameWnd::GetActiveView();
CFrameWnd::GetActiveDocument();

View和Document的通信
程序员通过改写CMyView的如下函数达到View和Document通信的目的:
CView::OnInitialUpdate():负责view的初始化。
CView::OnUpdate():Frameword在Document发生变化时调用此函数,此为预留给程序员的“用Document的变化指导 View”的接口。
CView::OnDraw():该函数作为WM_PAINT的间接响应,负责View的更新。
CDocument::UpdateAllViews()/CView::OnUpdate()这一对函数是命令与执行的关系,调用 UpdateAllViews()就会通知所有的View,通知方法就是调用其OnUpdate()。


原创粉丝点击