1. 单文档视图应用程序和多文档的区别:
前者在某一时刻只能管理一个文档,而后者可以管理多个
2. 文档模板类
作用:用统一的方式创建框架、视图、文档对象。
CDocTemplate: 抽象基类,提供了所有文档模板的功能。
CSingleDocTemplate:单文档模板类
CSingleDocTemplate(
UINT nIDResource,//资源ID
CRuntimeClass* pDocClass,//文档类的运行时类信息
CRuntimeClass* pFrameClass,//框架类的运行时类信息
CRuntimeClass* pViewClass//视图类的运行时类信息
);
注意:定义文档、框架和视图类时需要动态创建的支持
3. 建一个win32简单应用程序, 删除入口函数,将stdafx.h中的头文件 <windows.h> 更改为 <afxwin.h>,Project-->Settings菜单项中设置使用MFC动态库,需要自己添加菜单资源,File->new ->Resourse Script ,插入Menu
// Sdi.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "resource.h"
#include <afxext.h>
class CSdiDoc:public CDocument
{
DECLARE_DYNCREATE(CSdiDoc)
};
IMPLEMENT_DYNCREATE(CSdiDoc,CDocument)
class CSdiView:public CEditView
{
DECLARE_DYNCREATE(CSdiView)
};
IMPLEMENT_DYNCREATE(CSdiView,CEditView)
class CMainFrame:public CFrameWnd
{
DECLARE_DYNCREATE(CMainFrame)
};
IMPLEMENT_DYNCREATE(CMainFrame,CFrameWnd)
class CSdiApp:public CWinApp
{
public:
virtual BOOL InitInstance();
};
CSdiApp theApp;
BOOL CSdiApp::InitInstance()
{
//创建单文档模板
CSingleDocTemplate *pTemplate=
new CSingleDocTemplate(
IDR_MENU1,
RUNTIME_CLASS(CSdiDoc),
RUNTIME_CLASS(CMainFrame),
RUNTIME_CLASS(CSdiView));
//把文档模板添加到应用程序
AddDocTemplate(pTemplate);
//新建文档,(创建文档、框架和视图对象)
OnFileNew();
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
return TRUE;
}
分析:
AddDocTemplate函数的实现:我们设断点进入函数中得到
void CWinApp::AddDocTemplate(CDocTemplate* pTemplate)
{
if (m_pDocManager == NULL)
m_pDocManager = new CDocManager;
m_pDocManager->AddDocTemplate(pTemplate);
}
<pre name="code" class="cpp">void CDocManager::AddDocTemplate(CDocTemplate* pTemplate)
{
...
//在文档模板链表中添加新建的文档模板
m_templateList.AddTail(pTemplate); 534行
}
我们可以看出:
1. 应用程序没有直接管理模板,而是交给文档管理类管理模板
2. 在文档管理类使用链表保存文档模板,可以管理多个模板
OnFileNew()函数的实现:我们设断点进入函数中得到
void CWinApp::OnFileNew()
{
if (m_pDocManager != NULL)
m_pDocManager->OnFileNew();
}
void CDocManager::OnFileNew()
{
...
//获取保存的文档模板
CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetHead();
//调用文档模板的OpenDocumentFile()函数
pTemplate->OpenDocumentFile(NULL); 827行
}
CDocument* CSingleDocTemplate::OpenDocumentFile(...)
{
//创建新的文档对象
pDocument = CreateNewDocument(); 112行
//创建新的框架对象和框架窗口
pFrame = CreateNewFrame(pDocument, NULL); 132行
}
CFrameWnd* CDocTemplate::CreateNewFrame(...)
{
//创建新的框架对象
CFrameWnd* pFrame = 264行
(CFrameWnd*)m_pFrameClass->CreateObject();
//创建新的框架窗口
if (!pFrame->LoadFrame(m_nIDResource,...); 277行
}
调用LoadFrame时,产生WM_CREATE消息,在消息处理函数OnCreate()中,调用CreateView()函数,创建视图对象和视图窗口。
创建视图窗口时,产生WM_CREATE消息,在消息处理函数OnCreate()中,调用AddView()函数,文档与视图相互保存对方的地址。
画出类之间的调用关系图
CWinApp
|->m_pDocManager(CDocManager*)
|->m_templateList (CSingleDocTemplate*)
|->m_pOnlyDoc (CDocument*)
|->m_pMainWnd(CFrameWnd*)
|->m_pActiveView(CView*)
|->m_pDocument (CDocument*)
|->m_viewList (CView*)
结论:MFC各个类之间的关系实质上通过包含对方地址产生的