深入浅出文档视图架构之文档模板覆盖
民生风情 2021-08-25 01:54 字号: 大 中 小
前文我们提到,由于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的深层机理刨根究底,\"拨开云雾见月明\"的过程是艰辛的!查看本文来源
重庆皮肤病性病医院排名孩子不爱吃饭
渭南看白癜风哪家医院专业
-
-
恩惠欧冠决赛主裁公布执法红军输场曼联逆巴黎点
欧冠决赛主裁公布 执法红军输场 曼联逆巴黎点球斯科米纳欧...
2020-09-17 | 民生风情
-
-
孙杨1500自退赛赛前突发心脏不适
孙杨1500自退赛 赛前突发心脏不适【导读】北京时间8月10日消...
2020-08-05 | 民生风情
-
-
球英库首轮次轮真被鹈鹕的胃口吓到了
球英库+首轮+次轮!真被鹈鹕的胃口吓到了原本想给主席开个...
2020-07-04 | 民生风情
-
-
万宁市委书记兴隆要做些中高端房地产搭配
万宁市委书记:兴隆要做些中高端房地产万宁市在2008年取得了...
2020-05-29 | 民生风情
-
-
左腿受伤火箭对手主控伤停天无缘半决赛G搭配
左腿受伤!火箭对手主控伤停天 无缘半决赛G卢比奥VS保罗北京...
2020-05-28 | 民生风情
-
-
爱心市民看望见义勇为老人
爱心市民看望见义勇为老人连日来,曹宗诂老人不顾个人安危...
2019-07-15 | 民生风情