MFC能够将管理数据的代码和负责数据显示的代码分离开来,这正是由MFC的Document-View来提供的。Document/View是MFC的基石。
MFC中的Document只的是数据本身,即data set,data source,MFC只提供了一个Document的空壳类CDocument,通过在派生类中重写Serialize来实现数据的序列化与反序列化。View负责呈现Document中的数据。MFC提供了一个空壳的CView,若要显示数据,需要派生一个自己的View,同时需要重写OnDraw函数用于显示数据。CView派生自CWnd,因此可以接受一般的windows消息,如WM_PAINT,又因为也派生自CCmdTarget,因此也能接受WM_COMMAND消息。View呈现时是一个没有边框的窗口,真正呈现时其外围还有一个边框窗口,我们称之为Frame窗口。Frame的存在是为了显示不同的View,用来显示相同数据的不同显示(View)或不同数据的显示。
MFC把Document/View/Frame视为三位一体,每当用户打开一个文件,程序都应该创建这个三位一体的对象,MFC通过Document Template来管理这个三位一体。MFC共有2中Document Template 分别为CMultiDocTemplate和CSingleDocTemplate。CSingleDocTemplate并不表示智能打开一种类型的文件,而是同一时间只能打开一种类型文件。
从选择打开文件开始到文件内容被呈现出来都是通过DocumentTemplate完成。
CWinApp拥有一个对象指针CDocManager,该对象拥有template列表用来管理CDocumentTemplate,程序支持几种文件类型就应该有几个DocumentTemplate,在CMyWinApp::InitInstance中通过AddDocTemplate加入到CDocManager中。CDocTemplate拥有3个成员变量分别为Document、View、Frame的CRuntimeClass指针。另有一个成员变量IDResource用来表示呈现时采用的UI。
CObject对象代表一个链表,链表中的元素为CObject*。
在实际的编程任务中,Serialize函数是层层调用的,即最高层的抽象对象调用底层的对象,底层的对象在调用底层的对象。
当Framework收到WM_PAINT时会触发View的OnDraw函数,可以在此函数中执行绘图操作。同时为了实时反应鼠标在窗口上的移动轨迹,在OnMouseMove时也要进行绘图操作。
对象的Serialize是通过对象的层层向下调用直到最底层对象的Serialize调用,MFC的基础数据类别实现了自己的Serialize函数,因此可以直接使用。Framework调用Document::Serialize来序列化和反序列化对象。
对象如果想实现Serialize操作必须实现DECLARE_sERIAL宏,序列化操作是把对象写入文件的过程,反序列化操作比序列化复杂的多,实现读文件的同时还要实现对象的动态创建,因此可以序列化的类一定可以动态创建。
所有继承自CObject的类都可以实现IsKindOf的功能。
可以通过实现自己的Serialize函数简化对象的序列化与反序列化操作。MFC的Serialize操作会保存对象的类型信息。
通过调用CDocument::UpdateAllViews可以通知所有与document关联的窗口重绘。