文章类型: VC&C++
关键词: MFC,Document,View,Frame,深入探讨
内容摘要: 《深入浅出MFC》– Document-View深入探讨

《深入浅出MFC》– Document-View深入探讨

2016/8/23 9:25:05    来源:apple    阅读:

1.其实Document/View不是什么新东西,Xerox PARC实验室是这种观念的滥觞。它是Smalltalk环境中的关键性部分,在那里它被称为Model-View-Controller(MVC)。其中的Model就是MFC的Document,而Controller相当于MFC的Document Template。

 2.DocumentMFCCDocument里头被实例化。CDocument本身并无实际用途,他只是提供一个空壳。你应该从它派生一个自己的类,然后改写负责文件读写操作的Serilize函数。由于CDocument派生自CObject,所以他就有了CObject所支持的一切性质,包括RTTI、动态创建、文件读写。又由于它也派生自CCmdTarget,所以它可以接受来自菜单或工具栏的WM_COMMAND消息。

 3.View负责呈现Document中的数据。

ViewMFCCView里头被实例化,同样应该派生属于自己的View类,并且在类中改写专门负责显示数据的OnDraw函数或OnPrint函数。由于CView派生自CWnd,所以它可以接收一般的Windows消息,又由于它也派生自CCmdTarget,所以它可以接受来自菜单或工具栏的WM_COMMAND消息。

MFC中,一旦WM_PAINT发生,Framework会自动调用OnDraw函数,View事实上是个没有边框的窗口。真正出现时,其外围还有一个有边框的窗口,我们称之为Frame窗口。

 4.Document FrameView Frame

你可能愿意在使用者操作TEXT数据时,换一套TEXT专用的使用者界面,在使用者操作BITMAP数据时,换一套BITMAP专用的使用者界面。这份工作正式Frame窗口负责。

 5.Document Template

每当使用者欲打开一份文件,程序应该做出DocumentViewFrame各一份。这三个成为一个运行单元,由所谓的Document Template掌管。MFC有一个CDocTemplate负责此事,他又有两个派生类,分别是CMultiDocTemplateCSingleDocTemplate。如果你的程序能够处理两中数据类型,你必须制造两个Document Template,并使用AddDocTemplate函数将他们一一加入系统之中。

 6.谁来管理Document Template呢?是CWinApp。来看看InitInstance中应有的相关行为:

CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(
    IDR_MFCTYPE,
    RUNTIME_CLASS(CMfcDoc),
    RUNTIME_CLASS(CChildFrame), // custom MDI child frame
    RUNTIME_CLASS(CMfcView));
AddDocTemplate(pDocTemplate);

Document Template产生Document/View/Frame的行动:

image

7.当使用者单机File/New命令项,这一命令由CWinApp::OnFileNew接手处理。然后调用CDocManager::OnFileNew->CMultiDocTemplate::OpenDocumentFile.

OpenDocumentFileCreateNewDocument动态产生DocumentCreateNewFrame动态产生Document Frame。在CreateNewFrame中,不仅Frame被动态创建出来了,其对应窗口也以LoadFrame产生出来了。Document Frame窗口产生之际由于WM_CREATE的产生引发CFrameWnd::OnCreate被唤起。

image

不仅View对象被动态创建出来了,其对应的实际Windows窗口也以Create函数产生出来。

8.CDocTemplateCDocumentCViewCFrameWnd 之间的关系

CWinApp 拥有一个对象指针:CDocManager* m_pDocManager

CDocManager 拥有一个指标串行 CPtrList m_templateList 用来维护一系列的 Document Template。一个程序若支持两「种」文件型态,就应该有两份Document Templates,应用程序应该CMyWinApp::InitInstance 中以 AddDocTemplate 将这些 Document Templates 加入由 CDocManager 所维护的链表之中。

CDocTemplate 拥有三个成员变数, 分别持有 Document ViewFrame CRumtimeClass 指针,另有一个成员变量 m_nIDResource,用来表示此 Document 显现时应该采用的 UI 对象。这四份数据应该在 CMyWinApp::InitInstance 函数 建构 CDocTemplate(注1)时指定之,成为建构式的参数。当使用者欲打开一 份文件(通常是借着【File/Open】或【File/New】命令项),CDocTemplate 即可借由 Document/View/Frame CRuntimeClass 指标(注2)进行动态生成。

1:在此我们必须有所选择,要不就使用 CSingleDocTemplate,要不就使用 CMultiDocTemplate 两者都是 CDocTemplate 的衍生类别。如果你选用 CSingleDocTemplate,它有一个成员变数 CDocument* m_pOnlyDoc,亦即它一次只能打开一份 Document。如果你选用 CMultiDocTemplate,它有一个成员变数 CPtrList m_docList,表示它能同时打开多个 Documents

CDocument 有一个成员变数 CDocTemplate* m_pDocTemplate,回指其Document Template;另有一个成员变量 CPtrList m_viewList,表示它可以同时维护一系列的 Views

CFrameWnd 有一个成员变量 CView* m_pViewActive 指向目前正作用中的View

CView 有一个成员变量 CDocument* m_pDocument,指向相关的 Document

image

9.MFC Collection Classes

image

MFC Collection classes所支持的对象中,有两种特别需要说明,一是Ob,一是Ptr

Ob表示派生自CObject的任何对象。MFC提供CObListCObArray两种类。

Ptr表示对象指针。MFC提供CPtrListCPtrArray两种类。

10.Serializable的必要条件

欲让一个对象有Serialize能力,它必须派生自一个Serializable类。一个类意欲成为Serializable,必须有下列五大条件;

        1.  CObject派生下来。如此一来可保有RTTIDynamicCreation等机能。

        2.  类的声明部分必须有DECLARE_SERIAL宏。此宏需要一个参数:类名称。

        3.  类的实现部分必须有IMPLEMENT_SERIAL宏。此宏需要三个参数:一是类名称,三是schema no.

        4.  改写Serialize虚函数,使它能够适当地把类的成员变量写入文件中。

        5.  为经类加上一个default构造函数(也就是无参数之构造函数)。这个条件常为人所忽略,但它是必要的,因为若一个对象来自文件,MFC必须先动态创建它,而且在没有任何参数的情况下调用其构造函数,然后才从文件中读出对象数据。

一个类若要能够进行Serializable操作,必须准备Serialize函数,并且在类别型录网中自己的那个CRuntimeClass元素里的schema字段里设置0xFFFF以外的号码。

11.CArchive类管理文件缓冲区。它是Serialize的对象。CArchive针对许多C++数据类型,windows数据类型以及CObject派生类定义了operator<<operator>>重载运算符。

一个C++类如果想要有Serialization机制,就得直接或间接派生自CObject。为的是从CObject派生下列三个运算符:

_AFX_INLINE CArchive &AFXAPI operator<<(CArchive&ar,const CObject*pOb);

_AFX_INLINE CArchive &AFXAPI operator>>(CArchive&ar,CObject*&2pOb);

_AFX_INLINE CArchive &AFXAPI operator>>(CArchive&ar,const CObject*&pOb);

一个类如果希望有Serialization机制,它的第二要件就是使用SERIAL宏。

这个宏包含DYNCRETE宏,并且在类的声明之中加上:

friend CArchive &AFXAPI operator>>(CArchive&ar,class_name* &pOb);

在类的应用程序文件中加上:

CArchive &AFXAPI operator>>(CArchive&ar,class_name*&pOb) \

{ pOb=(class_name*)ar.ReadObject(RUNTIME_CLASS(class_name)); \

       return ar;}

12.当多个视图显示同一个文档,为了保持各个视图操作的文档内容的一致性,需要以消息通知使用同一份文档的其他视图,CView中有三个虚函数:

    1CView::OnInitialUpdate:负责View的初始化。

    2CView::OnUpdate,当FrameWork调用此函数时,表示Document的内容已经发生了变化。

    3CView::OnDraw:WM_PAINT消息时会调用此函数,此函数负责更新View窗口的内容。

让所有的View窗口同步更新数据的关键在于两个函数:

    1CDocument::UpdateAllViews,它会遍历使用这个文档的各个视图,逐个调用它们的OnUpdate函数。

    2CView::OnUpdate,这是个虚函数,可以改写。它的作用就是告诉Viewdocument的内容已经改变,你需要更新了。

具体步骤为:
    1:
CView中调用GetDocument获得CDocument指针。

    2:CView中调用CDocument::OnUpdateAllViews;

    3:所有使用这一份Documentview都被调用OnUpdate

image

转载请标注来源:http://www.blogfshare.com

ByAloneMonkey

本文链接:http://www.blogfshare.com/mfc-six.html




↑ 上一篇文章:DOC,VIEW,FRAME互相调用 关键词:vc,doc,frame,view 发布日期:2016/8/23 9:09:58
↓ 下一篇文章:MFC中的MainFrame Dlg,App,Doc,View的关系 关键词:MFC中的MainFrame,Dlg,App,Doc,V.. 发布日期:2016/8/23 9:39:28
相关文章:
在MFC中,如何获取CWinApp,CMainFrame,CChildFrame,CDocument,CView 关键词:在MFC中,如何获取CWinApp,CMainFrame,CChildFrame,CDocume.. 发布日期:2017-10-19 16:12
MFC中的MainFrame Dlg,App,Doc,View的关系 关键词:MFC中的MainFrame,Dlg,App,Doc,View的关系 发布日期:2016-08-23 09:39
DOC,VIEW,FRAME互相调用 关键词:vc,doc,frame,view 发布日期:2016-08-23 09:09
相关目录:.NETVC&C++软件开发
我要评论
正在加载评论信息......