目录
多文档视图架构
模仿多文档视图架构
执行流程
多文档视图架构
一个多文档视图架构运行后会是下面的样子:
内部的子框架窗口就相当于一个单文档视图架构,多文档视图架构就相当于在外面套一层框架窗口。
特点:可以管理多个文档(可以有多个文档类对象,即可以有多个数据)区别于单文档视图架构
模仿多文档视图架构
参与架构的类: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()函数,创建文档类对象,创建子框架类对象,创建子框架窗口,创建视图类对象,创建视图窗口,文档类对象和视图类对象关联