目录

多文档视图架构

模仿多文档视图架构

执行流程


多文档视图架构

一个多文档视图架构运行后会是下面的样子:

内部的子框架窗口就相当于一个单文档视图架构,多文档视图架构就相当于在外面套一层框架窗口。

特点:可以管理多个文档(可以有多个文档类对象,即可以有多个数据)区别于单文档视图架构

模仿多文档视图架构

参与架构的类:CMDIFrameWnd(主框架窗口)、CMDIChildWnd(子框架窗口)、CWinApp(应用程序类)、CView(视图类)、CDocument(文档类)

需要用到的类:CDocTemplate(文档模板类)、CMultiDocTemplate(多文档模板类,文档模板类的子类)、CDocManager(文档管理类)

代码如下:

#include #include "resource.h"class CMyDoc : public CDocument{DECLARE_DYNCREATE( CMyDoc )};IMPLEMENT_DYNCREATE( CMyDoc, CDocument )class CMyView : public CView{DECLARE_DYNCREATE( CMyView )public:virtual void OnDraw( CDC* pDC );};IMPLEMENT_DYNCREATE( CMyView, CView )// 视图类必须重写OnDraw虚函数void CMyView::OnDraw( CDC* pDC ){pDC->TextOut( 100, 100, "我是视图窗口" ); }class CMyChild : public CMDIChildWnd{ DECLARE_DYNCREATE( CMyChild )};IMPLEMENT_DYNCREATE( CMyChild, CMDIChildWnd )// 继承主框架窗口类的类不能使用动态创建机制class CMyFrameWnd : public CMDIFrameWnd{ //自己造主框架窗口类的对象};class CMyWinApp : public CWinApp{//自己造应用程序类的对象public:virtual BOOL InitInstance( );};BOOL CMyWinApp::InitInstance( ){CMyFrameWnd* pFrame = new CMyFrameWnd;// new一个主框架窗口类对象pFrame->LoadFrame( IDR_MENU1 );// 给主框架窗口挂上菜单m_pMainWnd = pFrame; // theApp->m_pMainWnd =主框架窗口类对象pFrame->ShowWindow( SW_SHOW );pFrame->UpdateWindow( );// new一个多文档类对象CMultiDocTemplate* pTemplate = new CMultiDocTemplate( IDR_MENU2,// 给子框架窗口挂上菜单RUNTIME_CLASS(CMyDoc),RUNTIME_CLASS(CMyChild),RUNTIME_CLASS(CMyView));// AddDocTemplate( pTemplate );OnFileNew( );//创建文档类对象,创建子框架类对象,创建子框架窗口,创建视图类对象,创建视图窗口,文档类对象和视图类对象关联OnFileNew( );//创建文档类对象,创建子框架类对象,创建子框架窗口,创建视图类对象,创建视图窗口,文档类对象和视图类对象关联OnFileNew( );//创建文档类对象,创建子框架类对象,创建子框架窗口,创建视图类对象,创建视图窗口,文档类对象和视图类对象关联return TRUE;}CMyWinApp theApp;//爆破点 

运行结果:

注意:需要给一个字符串资源,用于(父、子)框架窗口的标题命名

执行流程

在这里下断点,看看主框架窗口类对象的创建,this指针是pFrame主框架窗口类对象

调用函数LoadFrame(),this指针是pFrame主框架窗口类对象

调用Create函数创建

调用CreateEx函数,接下来就是之前分析的:

  • 给CREATESTRUCT cs; 结构体成员赋值
  • 调用PreCreateWindow(cs) :(1)注册窗口类(2)cs为空的成员重新赋值
  • AfxHookWindowCreate(this); (1)埋个钩子,类型是WHCBD (2)this是pFrame,保存到全局变量_AFX_THREAD_STATE中
  • 调用WIN API函数CreateWindowEx 创建主框架消息,消息会被钩子处理函数勾走。(1)pFrame对象与框架句柄绑定 (2)调用AfxWndProc函数

创建一个多文档模板类对象,触发构造函数,this指针是pTemplate

进入构造函数,接下来会调用父类的构造函数

赋值给多文档模板类对象的成员变量

m_doclist是多文档模板类对象pTemplate的成员变量,保存多个文档类对象地址

断言判断要求必须是空,之后的文档类对象会保存到这里

调用函数AddDocTemplate(),this指针是theApp

theApp对象的一个成员变量是m_pDocManager

调用函数AddDocTemplate(),this指针是m_pDocManager

把多文档模板类对象保存到m_templateList中

函数执行完毕,就形成下面的关系

调用函数OnFileNew( );this指针是theApp

调用函数OnFileNew( );this指针是theApp的成员m_pDocManager,文档管理类对象地址

取出多文档模板类对象地址,存储在pTemplate

调用函数OpenDocumentFile,函数内部this为多文档模板类对象地址

函数内部this为多文档模板类对象地址,调用函数CreateNewDocument();this指针是多文档模板类对象地址

动态创建文档类对象,并返回对象地址;

调用函数AddDocument()函数内部this为多文档模板类对象地址

将文档类对象扔到多文档模板类的链表成员中

调用CreateNewFrame函数内部this为多文档模板类对象地址

动态创建框子架类对象,并返回对象地址

创建子框架窗口

所以OnFileNew()函数,创建文档类对象,创建子框架类对象,创建子框架窗口,创建视图类对象,创建视图窗口,文档类对象和视图类对象关联