【CmultiDocTemplate】document template MFC的document/view结构

2012.9.5 多文档 CmultiDocTemplate()

MSDN 

CMultiDocTemplate::CMultiDocTemplate 


CMultiDocTemplate( 
 UINT nIDResource, 
 CRuntimeClass* pDocClass,
 CRuntimeClass* pFrameClass,
 CRuntimeClass* pViewClass 
);

CMultiDocTemplateEx::CMultiDocTemplateEx(   UINT   nIDResource,  

CRuntimeClass*   pDocClass, 
CRuntimeClass*   pFrameClass,
 
CRuntimeClass*   pViewClass   ,
 
UINT   *arID,int   n):   CMultiDocTemplate(nIDResource,pDocClass,pFrameClass,pViewClass)
 
{
 
}
 

nIDResource构造函数的第一个参数是一个资源ID,该资源用于提供该文档类型的菜单、快捷键、按钮等。

CRuntimeClass*   pDocClass,  //文档
CRuntimeClass*   pFrameClass,
 //包含视的窗口
CRuntimeClass*   pViewClass  
//与上面文档关联的视

注册一个模板; http://topic.csdn.net/t/20040412/16/2955609.htm 


Example
 :
//example for CMultiDocTemplate
BOOL CMyApp::InitInstance()
{
        // ...
        // Establish all of the document types
        // supported by the application
 
        AddDocTemplate( new CMultiDocTemplate( IDR_SHEETTYPE,
                            RUNTIME_CLASS( CSheetDoc ),
                            RUNTIME_CLASS( CMDIChildWnd ),
                            RUNTIME_CLASS( CSheetView ) ) );
 
        AddDocTemplate( new CMultiDocTemplate( IDR_NOTETYPE,
                            RUNTIME_CLASS( CNoteDoc ),
                            RUNTIME_CLASS( CMDIChildWnd ),
                            RUNTIME_CLASS( CNoteView ) ) );
        // ...
}

Here is a second example.

BOOL CYourApp::InitInstance()
{
   // Normally, an application creates a document 
   // template and registers it with MFC as a part
   // of its initialization.
 
   // IDR_SAMPLERESOURCE is a resource ID string; see
   // the CDocTemplate class overview documentation
   // for more information on its format.
 
   // The next three parameters use the RUNTIME_CLASS()
   // macro to get runtime type information for the doc,
   // frame, and view classes that will be associated
   // by the template.
 
   CMultiDocTemplate* pDocTemplate;
   pDocTemplate = new CMultiDocTemplate(
      IDR_SAMPLERESOURCE,
      RUNTIME_CLASS(CYourDoc),
      RUNTIME_CLASS(CChildFrame),
      RUNTIME_CLASS(CYourViewClass));
 
   // After the following call, MFC is aware of the doc
   // template and will free it when the application is
   // shut down. The doc templates known to MFC will
   // automatically be used when CWinApp:OnFileOpen()
   // or CWinApp::OnFileNew() are called.
 
   AddDocTemplate(pDocTemplate);
 
   // You might have other initialization code ...
   // ...
 
   return TRUE;
}

 

更多:

     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);


IDR_CMyDocTypeTYPE:传给构造函数的第一个参数是一个资源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()。

原文:http://www.sunhongfeng.com/2010/01/docframeview/

posted on 2022-10-04 01:30  bdy  阅读(52)  评论(0编辑  收藏  举报

导航