1、文档类CDocument
在"文档/视图"架构的MFC程序中,文档是 一个CDocument派生对象,它负责存储应用程序的数据,并把这些信息提供给应用程序的其余部分。CDocument类对文档的建立及归档提供 支持并提供了应用程序用于控制其数据的接口,类CDocument的声明如下:
/ // class CDocument is the main document data abstraction class CDocument : public CCmdTarget { DECLARE_DYNAMIC(CDocument) public: // Constructors CDocument();
// 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(); virtual void ReportSaveLoadException(LPCTSTR lpszPathName, CException* e,BOOL bSaving,Uint nIDPDefault); virtual CFile* GetFile(LPCTSTR lpszFilename,Uint nOpenFlags, CFileException* pError); virtual void ReleaseFile(CFile* pFile,BOOL bAbort);
// advanced overridables,closing down frame/doc,etc. virtual BOOL CanCloseFrame(CFrameWnd* pFramE); virtual BOOL SaveModified(); // return TRUE if ok to conTinue virtual void PreCloseFrame(CFrameWnd* pFramE);
// Implementation 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 BOOL m_bEmbedded; // TRUE => document is being created by OLE
#ifdef _DEBUG virtual void Dump(CDumpContext&) const; virtual void AssertValid() const; #endif //_DEBUG virtual ~CDocument();
// implementation Helpers virtual BOOL DoSave(LPCTSTR lpszPathName,BOOL breplace = TRUE); virtual BOOL DoFileSave(); virtual void updateFrameCounts(); void DisconnectViews(); void SendInitialupdate();
// overridables for implementation virtual HMENU GetDefaultMenu(); // get menu depending on state virtual HACCEL GetDefaultAccelerator(); virtual void OnIdle(); virtual void OnFinalRelease();
virtual BOOL OnCmdMsg(Uint nID,int nCode,void* pExtra,AFX_CMDHANDLERINFO* pHandlerInfo); friend class CDocTemplate;
protected: // file menu commands //{{AFX_MSG(CDocument) afx_msg void OnFileClose(); afx_msg void OnFileSave(); afx_msg void OnFileSaveAs(); //}}AFX_MSG // mail enabling afx_msg void OnFileSendMail(); afx_msg void OnupdateFileSendMail(CCmdUI* pCmdUI); DECLARE_@R_673_8798@GE_MAP() }; |
一个文档可以有多个视图,每 一个文档都维护 一个与之相关视图的链表(CptrList类型的 m_viewList实例)。CDocument::AddView将 一个视图连接到文档上,并将视图的文档指针指向该文档:
void CDocument::AddView(CView* pView) { ASSERT_VALID(pView); ASSERT(pView->m_pDocument == null); // must not be already attached ASSERT(m_viewList.Find(pView,NULL) == null); // must not be in list
m_viewList.AddTail(pView); ASSERT(pView->m_pDocument == null); // must be un-attached pView->m_pDocument = this;
OnChangedViewList(); // must be the last thing done to the document } |
CDocument: :removeView 则完成与CDocument::AddView相反的工作:
void CDocument::removeView(CView* pView) { ASSERT_VALID(pView); ASSERT(pView->m_pDocument == this); // must be attached to us
m_viewList.RemoveAt(m_viewList.Find(pView)); pView->m_pDocument = NULL;
OnChangedViewList(); // must be the last thing done to the document } |
从CDocument::AddView和CDocument: :removeView 函数可以看出,在与文档关联的视图被移走或新加入时CDocument::OnChangedViewList将被 调用:
void CDocument::OnChangedViewList() { // if no more views on the document,delete ourself // not called if Directly closing the document or terminaTing the app if (m_viewList.IsEmpty() && m_bAutoDelete) { OnCloseDocument(); return; }
// update the frame counts as needed updateFrameCounts(); } |
CDocument::DisconnectViews将所有的视图都与文档"失连":
void CDocument::DisconnectViews() { while (!m_viewList.IsEmpty()) { CView* pView = (CView*)m_viewList.RemoveHead(); ASSERT_VALID(pView); ASSERT_KINDOF(CView,pView); pView->m_pDocument = NULL; } } |
实际上,类CDocument对视图的管理与类CD OCManager对文档模板的管理及CDocTemplate对文档的管理 非常类似,少不了的,类CDocument中可遍历对应的视图(出现GetFirstXXX和GetNextXXX两个 函数):
POSITION CDocument::GetFirstViewPosition() const { return m_viewList.GetHeadPosition(); }
CView* CDocument::GetNextView(POSITION& rPosition) const { ASSERT(rPosition != BEFORE_START_POSITION); // use CDocument::GetFirstViewPosition instead ! if (rPosition == NULL) return NULL; // nothing left CView* pView = (CView*)m_viewList.GetNext(rPosition); ASSERT_KINDOF(CView,pView); return pView; } |
CDocument::GetFile和CDocument: :releaseFile 函数完成对参数lpszFil ename指定文档的打开与 关闭操作:
CFile* CDocument::GetFile(LPCTSTR lpszFilename, CFileException* pError) { CMirrorFile* pFile = new CMirrorFile; ASSERT(pFile != null); if (!pFile->Open(lpszFilename,nOpenFlags,pError)) { delete pFile; pFile = NULL; } return pFile; }
void CDocument::releaseFile(CFile* pFile,BOOL bAbort) { ASSERT_KINDOF(CFile,pFilE); if (bAbort) pFile->Abort(); // will not throw an exception else pFile->Close(); delete pFile; } |
CDocument类的OnNewDocument、OnOpenDocument、OnSaveDocument及OnCloseDocument这一组成员 函数用于创建、打开、保存或 关闭一个文档。 在这一组 函数中,上面的CDocument::GetFile和CDocument: :releaseFile两个 函数得以 调用:
BOOL CDocument::OnOpenDocument(LPCTSTR lpszPathName) { if (IsModified()) TRACE0("Warning: OnOpenDocument replaces an unsaved document./n");
CFileException fe; CFile* pFile = GetFile(lpszPathName, CFile::modeRead|CFile::shareDenyWrite,&fE); if (pFile == NULL) { ReportSaveLoadException(lpszPathName,&fe,@R_489_11372@SE,AFX_IDP_Failed_TO_OPEN_DOC); return @R_489_11372@SE; }
deleteContents(); SetModifiedFlag(); // dirty during de-serialize
CArchive loadArchive(pFile,CArchive::load | CArchive::bNoFlushOnDelete); loadArchive.m_pDocument = this; loadArchive.m_bForceFlat = @R_489_11372@SE; TRY { CWaitcursor wait; if (pFile->GetLength() != 0) serialize(loadArchivE); // load me loadArchive.Close(); ReleaseFile(pFile,@R_489_11372@SE); } CATCH_ALL(E) { ReleaseFile(pFile,TRUE); deleteContents(); // remove Failed contents
TRY { ReportSaveLoadException(lpszPathName,e,AFX_IDP_Failed_TO_OPEN_DOC); } END_TRY deletE_EXCEPTION(E); return @R_489_11372@SE; } END_CATCH_ALL
SetModifiedFlag(false); // start off with unmodified
return TRUE; } |
|
|