首页 >> 民生风情

深入浅出文档视图架构之文档模板覆盖

民生风情  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的深层机理刨根究底,\"拨开云雾见月明\"的过程是艰辛的!查看本文来源

重庆皮肤病性病医院排名
孩子不爱吃饭
渭南看白癜风哪家医院专业
推荐资讯