MFC的Document/View结构能够将管理数据的程序代码负责数据显示的程序代码分离出来。主要包括这样几个类:CDocManager,CDocTemplate,CDocument,CView,CFrameWnd。在介绍之前源码如下:
CDocManager类的部分定义
class CDocManager : public CObject { public: virtual CDocument* OpenDocumentFile(LPCTSTR lpszFileName); // open named file virtual BOOL SaveAllModified(); // save before exit virtual void CloseAllDocuments(BOOL bEndSession); // close documents before exiting virtual BOOL DoPromptFileName(CString& fileName, UINT nIDSTitle,DWORD lFlags, BOOL bOpenFileDialog, CDocTemplate* pTemplate); virtual void OnFileNew(); virtual void OnFileOpen(); virtual POSITION GetFirstDocTemplatePosition() const; virtual CDocTemplate* GetNextDocTemplate(POSITION& pos) const; protected: CPtrList m_templateList; //保存APP里的所有CDocTemplate };
CDocTemplate类的部分定义
class CDocTemplate : public CCmdTarget { protected: CDocTemplate(UINT nIDResource, CRuntimeClass* pDocClass,CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass); public: virtual void LoadTemplate(); public: virtual POSITION GetFirstDocPosition() const = 0; virtual CDocument* GetNextDoc(POSITION& rPos) const = 0; public: virtual void AddDocument(CDocument* pDoc); // must override virtual void RemoveDocument(CDocument* pDoc); // must override enum DocStringIndex { windowTitle, // default window title docName, // user visible name for default document fileNewName, // user visible name for FileNew // for file based documents: filterName, // user visible name for FileOpen filterExt, // user visible extension for FileOpen // for file based documents with Shell open support: regFileTypeId, // REGEDIT visible registered file type identifier regFileTypeName, // Shell visible registered file type name }; virtual BOOL GetDocString(CString& rString,enum DocStringIndex index) const; public: virtual CDocument* CreateNewDocument(); virtual CFrameWnd* CreateNewFrame(CDocument* pDoc, CFrameWnd* pOther); virtual void InitialUpdateFrame(CFrameWnd* pFrame, CDocument* pDoc,BOOL bMakeVisible = TRUE); virtual BOOL SaveAllModified(); // for all documents virtual void CloseAllDocuments(BOOL bEndSession); virtual CDocument* OpenDocumentFile(LPCTSTR lpszPathName, BOOL bMakeVisible = TRUE) = 0; virtual void SetDefaultTitle(CDocument* pDocument) = 0; public: BOOL m_bAutoDelete; virtual ~CDocTemplate() = 0; virtual void OnIdle(); // for all documents virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra,AFX_CMDHANDLERINFO* pHandlerInfo); protected: UINT m_nIDResource; // IDR_ for frame/menu/accel as well CRuntimeClass* m_pDocClass; // class for creating new documents CRuntimeClass* m_pFrameClass; // class for creating new frames CRuntimeClass* m_pViewClass; // class for creating new views CRuntimeClass* m_pOleFrameClass; // class for creating in-place frame CRuntimeClass* m_pOleViewClass; // class for creating in-place view CString m_strDocStrings; // '/n' separated names // The document names sub-strings are represented as _one_ string: // windowTitle/ndocName/n ... (see DocStringIndex enum) };
CSingleDocTemplate /CMultiDocTemplate 类的部分定义
class CSingleDocTemplate : public CDocTemplate { public: CSingleDocTemplate(UINT nIDResource, CRuntimeClass* pDocClass, CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass); public: virtual ~CSingleDocTemplate(); virtual void AddDocument(CDocument* pDoc); virtual void RemoveDocument(CDocument* pDoc); virtual POSITION GetFirstDocPosition() const; virtual CDocument* GetNextDoc(POSITION& rPos) const; virtual CDocument* OpenDocumentFile(LPCTSTR lpszPathName, BOOL bMakeVisible = TRUE); virtual void SetDefaultTitle(CDocument* pDocument); protected: CDocument* m_pOnlyDoc; //只有一个文档 }; class CMultiDocTemplate : public CDocTemplate { public: CMultiDocTemplate(UINT nIDResource, CRuntimeClass* pDocClass, CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass); public: virtual ~CMultiDocTemplate(); virtual void LoadTemplate(); virtual void AddDocument(CDocument* pDoc); virtual void RemoveDocument(CDocument* pDoc); virtual POSITION GetFirstDocPosition() const; virtual CDocument* GetNextDoc(POSITION& rPos) const; virtual CDocument* OpenDocumentFile(LPCTSTR lpszPathName, BOOL bMakeVisible = TRUE); virtual void SetDefaultTitle(CDocument* pDocument); protected: CPtrList m_docList; // 保存这类文档的所有文档 UINT m_nUntitledCount; // start at 0, for "Document1" title };
CDocument类的部分定义
class CDocument : public CCmdTarget { // Attributes public: const CString& GetTitle() const; virtual void SetTitle(LPCTSTR lpszTitle); const CString& GetPathName() const; virtual void SetPathName(LPCTSTR lpszPathName, BOOL bAddToMRU = TRUE); CDocTemplate* GetDocTemplate() const; virtual BOOL IsModified(); virtual void SetModifiedFlag(BOOL bModified = TRUE); // Operations void AddView(CView* pView); void RemoveView(CView* pView); virtual POSITION GetFirstViewPosition() const; virtual CView* GetNextView(POSITION& rPosition) const; // Update Views (simple update - DAG only) void UpdateAllViews(CView* pSender, LPARAM lHint = 0L,CObject* pHint = NULL); // Overridables // Special notifications virtual void OnChangedViewList(); // after Add or Remove view virtual void DeleteContents(); // delete doc items etc // File helpers virtual BOOL OnNewDocument(); virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); virtual BOOL OnSaveDocument(LPCTSTR lpszPathName); virtual void OnCloseDocument(); protected: // default implementation CString m_strTitle; CString m_strPathName; CDocTemplate* m_pDocTemplate; CPtrList m_viewList; // list of views BOOL m_bModified; // changed since last saved public: BOOL m_bAutoDelete; // TRUE => delete document when no more views protected: afx_msg void OnFileClose(); //FILE/CLOSE afx_msg void OnFileSave(); //FILE/SAVE afx_msg void OnFileSaveAs(); //FILE/SAVEAS };
CView类的部分定义
class CView : public CWnd { public: CDocument* GetDocument() const; BOOL DoPreparePrinting(CPrintInfo* pInfo); // Overridables public: virtual void OnPrepareDC(CDC* pDC, CPrintInfo* pInfo = NULL); virtual void OnInitialUpdate(); // called first time after construct protected: //CDocument::UpdateAllViews中调用 //也可以知道调用更新视图内容 virtual void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint); virtual void OnDraw(CDC* pDC) = 0; // Printing support virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); // must override to enable printing and print preview virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); virtual void OnPrint(CDC* pDC, CPrintInfo* pInfo); virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); // Advanced: end print preview mode, move to point virtual void OnEndPrintPreview(CDC* pDC, CPrintInfo* pInfo, POINT point,CPreviewView* pView); // Implementation public: // Advanced: for implementing custom print preview BOOL DoPrintPreview(UINT nIDResource, CView* pPrintView,CRuntimeClass* pPreviewViewClass, CPrintPreviewState* pState); virtual void CalcWindowRect(LPRECT lpClientRect,UINT nAdjustType = adjustBorder); virtual CScrollBar* GetScrollBarCtrl(int nBar) const; static CSplitterWnd* PASCAL GetParentSplitter(const CWnd* pWnd, BOOL bAnyState); protected: CDocument* m_pDocument; public: virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra,AFX_CMDHANDLERINFO* pHandlerInfo); public: afx_msg void OnFilePrint(); //FILE/PRINT afx_msg void OnFilePrintPreview(); //FILE/PREPRINT };
CFrameWnd类的部分定义
class CFrameWnd : public CWnd { public: virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle = WS_OVERLAPPEDWINDOW, const RECT& rect = rectDefault, CWnd* pParentWnd = NULL, // != NULL for popups LPCTSTR lpszMenuName = NULL, DWORD dwExStyle = 0, CCreateContext* pContext = NULL); // dynamic creation - load frame and associated resources virtual BOOL LoadFrame(UINT nIDResource, DWORD dwDefaultStyle = WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, CWnd* pParentWnd = NULL, CCreateContext* pContext = NULL); // Attributes virtual CDocument* GetActiveDocument(); CView* GetActiveView() const; // active view or NULL void SetActiveView(CView* pViewNew, BOOL bNotify = TRUE); // Operations virtual void RecalcLayout(BOOL bNotify = TRUE); virtual void ActivateFrame(int nCmdShow = -1); void InitialUpdateFrame(CDocument* pDoc, BOOL bMakeVisible); void SetTitle(LPCTSTR lpszTitle); CString GetTitle() const; virtual CMenu* GetMenu() const; virtual BOOL SetMenu(CMenu* pMenu); protected: virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext); private: CView* m_pViewActive; // current active view };
App/Frame/View/CDoucument的关系如图:
下面是文字整理:
1.CWinApp拥有一个对象指针:CDocManager* m_pDocManager.
2.CDocManager拥有一个指针链表CPtrList m_templateList,用来维护一系列的Document Template。一个程序若支持两“种”文件类型,就应该有两份Document Template,应用程序应该在CMyWinApp::Instance中以AddDocTemplate将这些Document Templates加入到CDocManager所维护的链表之中。
3.CDocTemplate拥有三个成员变量,分别是Document,View,Frame,的CRuntimeClass的指针,另有一个成员变量m_nIDResoure,用来表示Document显示时应该采用的UI对象,这四份数据应该在CMyWinApp::InitInstance函数构造CDocTemplate时指定,成为构成函数的参数。当使用者欲打开一份文件时(通常接着【FILE/OPEN】或【FILE/NEW】),CDocTemplate可以借着CRuntimeClass指针动态创建响应的对象。
4.CDocument有一个成员变量CDocTemplate* m_pDocTemplate,回指DocTemplate;另一个成员变量CPtrList viewList,表示它可以同时维护一些列的Views.
5.CFrameWnd有一个成员变量CView* m_pViewActive,指向当前活动的View.
6.CView有一个成员变量CDocument* m_pDocument,指向相关的Document.
从一个视图类取得另一视图类的指针可以这样。
CView* CMyView::GetView(CRuntimeClass* pClass) { CMyDoc* pDoc=(CMyDoc*)GetDocument(); CView* pView; POSITION pos=pDoc->GetFirstViewPosition(); while(pos!=NULL){ pView=pDoc->GetNextView(pos); if(!pView->IsKindOf(pClass)) break; } if(!pView->IsKindOf(pClass)){ AfxMessageBox("Connt Locate the View."); return NULL; } return pView; }