深入浅出MFC文档/视图架构之文档(1)
发布时间:2021-05-20 14:29:20 所属栏目:大数据 来源: https://blog.csdn.net/dragonf
导读:1、文档类CDocument 在"文档/视图"架构的MFC程序中,文档是一个CDocument派生对象,它负责存储应用程序的数据,并把这些信息提供给应用程序的其余部分。CDocument类对文档的建立及归档提供支持并提供了应用程序用于控制其数据的接口,类CDocument的声明如下
|
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_MESSAGE_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对视图的管理与类CDocManager对文档模板的管理及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函数完成对参数lpszFileName指定文档的打开与关闭操作:
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,FALSE,AFX_IDP_Failed_TO_OPEN_DOC);
return FALSE;
}
DeleteContents();
SetModifiedFlag(); // dirty during de-serialize
CArchive loadArchive(pFile,CArchive::load | CArchive::bNoFlushOnDelete);
loadArchive.m_pDocument = this;
loadArchive.m_bForceFlat = FALSE;
TRY
{
CWaitCursor wait;
if (pFile->GetLength() != 0)
Serialize(loadArchive); // load me
loadArchive.Close();
ReleaseFile(pFile,FALSE);
}
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 FALSE;
}
END_CATCH_ALL
SetModifiedFlag(FALSE); // start off with unmodified
return TRUE;
}
(编辑:北几岛)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!