深入浅出MFC文档/视图架构之文档模板(4)
发布时间:2021-07-06 05:51:30 所属栏目:大数据 来源: https://blog.csdn.net/dragonf
导读:? 前文我们提到,由于MFC的设计者将CSingleDocTemplate和CMultiDocTemplate的行为未进行规范的区分,它对仅仅对应一个文档的CSingleDocTemplate也提供了所谓的GetFirstDocPosition、GetNextDoc遍历操作,所以基类CDocTemplate的SaveAllModified和CloseAllDocu
?
|
前文我们提到,由于MFC的设计者将CSingleDocTemplate和CMultiDocTemplate的行为未进行规范的区分,它对仅仅对应一个文档的CSingleDocTemplate也提供了所谓的GetFirstDocPosition、GetNextDoc遍历操作,所以基类CDocTemplate的SaveAllModified和CloseAllDocuments函数(都是遍历)就可统一CSingleDocTemplate和CMultiDocTemplate两个本身并不相同类的SaveAllModified和CloseAllDocuments行为(实际上,对于CSingleDocTemplate而言,SaveAllModified和CloseAllDocuments中的"All"是没有太大意义的。教室里有1个老师和N个同学,老师可以对同学们说"所有同学",而学生对老师说"所有老师"相信会被当成神经病)。MFC的设计者们特意使用了"将错就错"的方法意图简化CSingleDocTemplate和CMultiDocTemplate类的设计,读者朋友可以不认同他们的做法。
CDocTemplate还提供了框架窗口的创建和初始化函数:
/
// Default frame creation
CFrameWnd* CDocTemplate::CreateNewFrame(CDocument* pDoc,CFrameWnd* pOther)
{
if (pDoc != NULL)
ASSERT_VALID(pDoc);
// create a frame wired to the specified document
ASSERT(m_nIDResource != 0); // must have a resource ID to load from
CCreateContext context;
context.m_pCurrentFrame = pOther;
context.m_pCurrentDoc = pDoc;
context.m_pNewViewClass = m_pViewClass;
context.m_pNewDocTemplate = this;
if (m_pFrameClass == NULL)
{
TRACE0("Error: you must override CDocTemplate::CreateNewFrame./n");
ASSERT(FALSE);
return NULL;
}
CFrameWnd* pFrame = (CFrameWnd*)m_pFrameClass->CreateObject();
if (pFrame == NULL)
{
TRACE1("Warning: Dynamic create of frame %hs Failed./n",m_pFrameClass->m_lpszClassName);
return NULL;
}
ASSERT_KINDOF(CFrameWnd,pFrame);
if (context.m_pNewViewClass == NULL)
TRACE0("Warning: creating frame with no default view./n");
// create new from resource
if (!pFrame->LoadFrame(m_nIDResource,WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE,// default frame styles
NULL,&context))
{
TRACE0("Warning: CDocTemplate couldn't create a frame./n");
// frame will be deleted in PostNcDestroy cleanup
return NULL;
}
// it worked !
return pFrame;
}
void CDocTemplate::InitialUpdateFrame(CFrameWnd* pFrame,CDocument* pDoc,BOOL bMakeVisible)
{
// just delagate to implementation in CFrameWnd
pFrame->InitialUpdateFrame(pDoc,bMakeVisible);
}
3. CWinApp与CDocManager/CDocTemplate类
应用程序CWinApp类对象与CDocManager和CDocTemplate类的关系是:CWinApp对象中包含一个CDocManager指针类型的共有数据成员m_pDocManager,CWinApp::InitInstance函数调用CWinApp::AddDocTemplate函数向链表m_templateList添加模板指针(实际上是调用前文所述CDocManager的AddDocTemplate函数)。另外,CWinApp也提供了GetFirstDocTemplatePosition和GetNextDocTemplate函数实现来对m_templateList链表进行访问(实际上也是调用了前文所述CDocManager的GetFirstDocTemplatePosition、GetNextDocTemplate函数)。我们仅摘取CWinApp类声明的一小部分:
class CWinApp : public CWinThread
{
…
CDocManager* m_pDocManager;
// Running Operations - to be done on a running application
// Dealing with document templates
void AddDocTemplate(CDocTemplate* pTemplate);
POSITION GetFirstDocTemplatePosition() const;
CDocTemplate* GetNextDocTemplate(POSITION& pos) const;
// Dealing with files
virtual CDocument* OpenDocumentFile(LPCTSTR lpszFileName); // open named file
void CloseAllDocuments(BOOL bEndSession); // close documents before exiting
// Command Handlers
protected:
// map to the following for file new/open
afx_msg void OnFileNew();
afx_msg void OnFileOpen();
int GetOpenDocumentCount();
…
};
来看CWinApp派生类CSDIExampleApp(单文档)、CMDIExampleApp(多文档)的InitInstance成员函数的例子(仅仅摘取与文档模板相关的部分):
BOOL CSDIExampleApp::InitInstance()
{
…
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(IDR_MAINFRAME,RUNTIME_CLASS(CSDIExampleDoc),
RUNTIME_CLASS(CMainFrame),// main SDI frame window
RUNTIME_CLASS(CSDIExampleView));
AddDocTemplate(pDocTemplate);
…
return TRUE;
}
BOOL CMDIExampleApp::InitInstance()
{
…
CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(IDR_MDIEXATYPE,
RUNTIME_CLASS(CMDIExampleDoc),
RUNTIME_CLASS(CChildFrame),// custom MDI child frame
RUNTIME_CLASS(CMDIExampleView));
AddDocTemplate(pDocTemplate);
…
}
读者朋友,看完本次连载,也许您有许多不明白的地方,这是正常的。因为其所讲解的内容与后续几次连载息息相关,我们愈往后看,就会愈加清晰。对于本次连载的内容,您只需要建立基本的印象。最初的浅尝辄止是为了最终的深入脊髓!
我们试图对MFC的深层机理刨根究底,"拨开云雾见月明"的过程是艰辛的!
(编辑:北几岛)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!