深入浅出MFC文档/视图架构之文档模板(3)
发布时间:2021-07-06 05:51:29 所属栏目:大数据 来源: https://blog.csdn.net/dragonf
导读:? CDocTemplate类的AddDocument、RemoveDocument成员函数使得CDocument* pDoc参数所指向的文档归属于本文档模板(通过将this指针赋值给pDoc所指向CDocument对象的m_pDocTemplate成员变量)或脱离与本文档模板的关系: void CDocTemplate::AddDocument(CDocume
?
|
CDocTemplate类的AddDocument、RemoveDocument成员函数使得CDocument* pDoc参数所指向的文档归属于本文档模板(通过将this指针赋值给pDoc所指向CDocument对象的m_pDocTemplate成员变量)或脱离与本文档模板的关系:
void CDocTemplate::AddDocument(CDocument* pDoc)
{
ASSERT_VALID(pDoc);
ASSERT(pDoc->m_pDocTemplate == NULL); // no template attached yet
pDoc->m_pDocTemplate = this;
}
void CDocTemplate::RemoveDocument(CDocument* pDoc)
{
ASSERT_VALID(pDoc);
ASSERT(pDoc->m_pDocTemplate == this); // must be attached to us
pDoc->m_pDocTemplate = NULL;
}
而CDocTemplate类的CreateNewDocument成员函数则首先调用CDocument运行时类的CreateObject函数创建一个CDocument对象,再调用AddDocument成员函数将其归属于本文档模板类:
CDocument* CDocTemplate::CreateNewDocument()
{
// default implementation constructs one from CRuntimeClass
if (m_pDocClass == NULL)
{
TRACE0("Error: you must override CDocTemplate::CreateNewDocument./n");
ASSERT(FALSE);
return NULL;
}
CDocument* pDocument = (CDocument*)m_pDocClass->CreateObject();
if (pDocument == NULL)
{
TRACE1("Warning: Dynamic create of document type %hs Failed./n",m_pDocClass->m_lpszClassName);
return NULL;
}
ASSERT_KINDOF(CDocument,pDocument);
AddDocument(pDocument);
return pDocument;
}
文档类对象由文档模板类构造生成,单文档模板类CSingleDocTemplate只能生成一个文档类对象,并用成员变量 m_pOnlyDoc 指向该对象;多文档模板类可以生成多个文档类对象,用成员变量 m_docList 指向文档对象组成的链表。
CSingleDocTemplate的构造函数、AddDocument及RemoveDocument成员函数都在CDocTemplate类相应函数的基础上增加了对m_pOnlyDoc指针的处理:
CSingleDocTemplate::CSingleDocTemplate(UINT nIDResource,
CRuntimeClass* pDocClass,CRuntimeClass* pFrameClass,
CRuntimeClass* pViewClass)
: CDocTemplate(nIDResource,pDocClass,pFrameClass,pViewClass)
{
m_pOnlyDoc = NULL;
}
void CSingleDocTemplate::AddDocument(CDocument* pDoc)
{
ASSERT(m_pOnlyDoc == NULL); // one at a time please
ASSERT_VALID(pDoc);
CDocTemplate::AddDocument(pDoc);
m_pOnlyDoc = pDoc;
}
void CSingleDocTemplate::RemoveDocument(CDocument* pDoc)
{
ASSERT(m_pOnlyDoc == pDoc); // must be this one
ASSERT_VALID(pDoc);
CDocTemplate::RemoveDocument(pDoc);
m_pOnlyDoc = NULL;
}
同样,CMultiDocTemplate类的相关函数也需要对m_docList所指向的链表进行操作(实际上AddDocument和RemoveDocument成员函数是文档模板管理其所包含文档的函数):
// CMultiDocTemplate document management (a list of currently open documents)
void CMultiDocTemplate::AddDocument(CDocument* pDoc)
{
ASSERT_VALID(pDoc);
CDocTemplate::AddDocument(pDoc);
ASSERT(m_docList.Find(pDoc,NULL) == NULL); // must not be in list
m_docList.AddTail(pDoc);
}
void CMultiDocTemplate::RemoveDocument(CDocument* pDoc)
{
ASSERT_VALID(pDoc);
CDocTemplate::RemoveDocument(pDoc);
m_docList.RemoveAt(m_docList.Find(pDoc));
}
由于CMultiDocTemplate类可包含多个文档,依靠其成员函数GetFirstDocPosition和GetNextDoc完成对文档链表m_docList的遍历:
POSITION CMultiDocTemplate::GetFirstDocPosition() const
{
return m_docList.GetHeadPosition();
}
CDocument* CMultiDocTemplate::GetNextDoc(POSITION& rPos) const
{
return (CDocument*)m_docList.GetNext(rPos);
}
而CSingleDocTemplate的这两个函数实际上并无太大的意义,仅仅是MFC要玩的某种"招数",这个"招数"高明吗?相信看完MFC的相关源代码后你或许不会这么认为,实际上CSingleDocTemplate的GetFirstDocPosition、GetNextDoc函数仅仅只能判断m_pOnlyDoc的是否为NULL:
POSITION CSingleDocTemplate::GetFirstDocPosition() const
{
return (m_pOnlyDoc == NULL) ? NULL : BEFORE_START_POSITION;
}
CDocument* CSingleDocTemplate::GetNextDoc(POSITION& rPos) const
{
CDocument* pDoc = NULL;
if (rPos == BEFORE_START_POSITION)
{
// first time through,return a real document
ASSERT(m_pOnlyDoc != NULL);
pDoc = m_pOnlyDoc;
}
rPos = NULL; // no more
return pDoc;
}
笔者认为,MFC的设计者们将GetFirstDocPosition、GetNextDoc作为基类CDocTemplate的成员函数是不合理的,一种更好的做法是将GetFirstDocPosition、GetNextDoc移至CMultiDocTemplate派生类。
CDocTemplate还需完成对其对应文档的关闭与保存操作:
BOOL CDocTemplate::SaveAllModified()
{
POSITION pos = GetFirstDocPosition();
while (pos != NULL)
{
CDocument* pDoc = GetNextDoc(pos);
if (!pDoc->SaveModified())
return FALSE;
}
return TRUE;
}
void CDocTemplate::CloseAllDocuments(BOOL)
{
POSITION pos = GetFirstDocPosition();
while (pos != NULL)
{
CDocument* pDoc = GetNextDoc(pos);
pDoc->OnCloseDocument();
}
}
(编辑:北几岛)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!