计算机二级

3773考试网计算机等级考试计算机二级正文

对MFC文档视图结构的深入分析

来源:fjzsksw.com 2010-8-10 15:02:29

 

1 总揽

招考网1.1 MFC文档视图结构程序结构总揽

招考网当我们使用MFC AppWizard生成一个MFC程序,选用所有默认的设置(当然也是Multiple Documents,本文讨论主要基于Multiple Documents,对于Single Document情况仅以简单表述提及,皆因后者和前者很多相似相同之处,但前者更为复杂,并且更加常用。),假设你的程序名称为A ,则你会得到CMainFrame、CChildFrame、CAboutDlg、CADoc、CAView、CAApp 6个类(Single Document 仅少一个CChildFrame类,其余均同)。这些类的具体含义将在后面给出,这里先要给出一个MFC 支持文档视图结构程序(以下简称App)的主要组成:

招考网1      一个App(对应类CAApp)可以包含多个文档模版(CDocTemplate),但是MFC AppWizard(无论是SDI还是MDI)都只是默认生成一个。但是在实际开发中一个文档模版不够,需要自己手工添加(在后面实际项目例子提供示例)。这个结构是通过MFC中CWinApp的成员变量CDocManager* m_pDocManager实现的,我们的CAApp正是继承自MFC提供的CWinApp类。

招考网2       CDocManager类则拥有一个指针链表CPtrList m_templateList来维护这些文档模版。这些文档模版都是在CAApp::InitInstance()中通过AddDocTemplate(pDocTemplate)。

招考网3       CDocTemplate拥有3个成员变量,分别保存着Document、View、Frame的CRuntimeClass指针,另外持有成员变量m_nIDResource,用来指定这个Document显示时候采用的菜单资源。这4份数据都在CAApp::InitInstance()中CDocTemplate的构造函数中指定。在Document中拥有一个回指CDocTemplate的指针(m_pDocTemplate)。

招考网4      一个文档可以有多个视图,由Document中成员变量CPtrList m_ViewList维护。

招考网5       CFrameWnd拥有一个成员变量CView* m_pActiveView指向当前活动的View。

招考网6      CView中拥有一个成员变量CDocument* m_pDocument指向该视图相关的Document。

招考网[注解]:①MFC SDI/MDI程序默认都默认生成了一个文档模版,并将这个文档模版Add到其文档模版的链表中,由于这是MFC默认提供的,因此这个文档模版会被插入到文档模版的第一个位置,而MFC也是通过这个文档模版的特定位置可以确定的。默认情况下,当我们点击File(Open)/ File(New)的时候,这个文档模版会被启用。

招考网于MFC SDI/MDI的知识:

招考网1      文档的本质:文档是用来保存数据以及关于数据的处理的,每当MFC SDI/MDI响应File(Open)/ File(New)的时候都会打开一份文档。文档可以拥有多个视图。文档和视图的关系可以这样理解:文档是被视图观察的对象。

招考网2       视图本质:视图在Windows中就是一个窗口,也就是一个可视化的矩形区域。视图是用来表示文档的数据的。但是每个视图必需依附于一个框架(SDI中是MainFrame,MDI是ChildFrame)。当然你可以自己去Create一个视图,并且去显示它。

招考网3      框架的本质:框架实际是也是一个Windows窗口。但是在框架上可以放置菜单、工具栏、状态栏等。而视图则放在框架的客户区。因此MFC中我们看到的窗口实际上Frame和View共同作用的结果。

招考网4       在某一时刻,程序中只有一个活动的文档、框架和视图,即当前的文档、框架、视图。

招考网1.2 MFC SDI/MDI各个类之间的互访

招考网在实际项目开发中用的最多就是各个类之间的互访问,这里将网络上和书籍中提到的做了一个总结,也是笔者在实际开发中都用到过的。

招考网2 文档、视图、框架之间的关联

招考网MFC SDI/MDI中的核心就在于文档、视图、框架之间的关联,形成了一个有机的可运作的整体。MFC提供了默认的关联关系,但是在实际的项目开发中很多时候需要动态进行他们的之间的关联。

招考网2.1 文档和视图间的关联

招考网使用MFC AppWizard声称MFC SDI/MDI程序,在App类的InitInstance()方法中有如下代码(假设Project名称均为Test):

招考网1       SDI中

招考网CSingleDocTemplate* pDocTemplate;

招考网pDocTemplate = new CSingleDocTemplate(

招考网IDR_MAINFRAME,

招考网RUNTIME_CLASS(CTestDoc),

招考网RUNTIME_CLASS(CMainFrame),       // main SDI frame window

招考网RUNTIME_CLASS(CTestView));

招考网AddDocTemplate(pDocTemplate);

招考网2      MDI中

招考网关于SDI/MDI:

招考网一、SDI一次只能打开一份document(与mutidoctemplate或者SingleDocTeplate无关)

招考网为了显示这份document,必须配备以下内容:

招考网A、相应的view(可以是多个,比如所切分视图)

招考网B、 相应的边框,其实就是mainframe

招考网C、 相应的IDR(比如说标题等

招考网二、MDI一次可以打开多个documents;

招考网A、 当这多个documents是不同类型时,每一类document必须配备相应的view 和边框(CMidChildwnd),至于怎么配置?由相应的DocTemplate来决定啦!

招考网B、当这多个documents是同一种类型时,只需配备一次即可。

招考网C、程序中只有一份document,但是执行了window->new window时,可以 打开第二个view,并且这个view也有一个边框midchlldwnd。

招考网SDI只能有一个框架窗口类和一个框架窗口对象(CMainFrame:CFrameWnd);

招考网MDI应用程序有两个框架窗口类,并且可以有多个框架对象,即:

招考网CMainFrame:CMDIFrameWnd 只有一个对应对象        有菜单和控制栏   无视图

招考网CChildFrame:CMDIChildWnd 每个子窗口对应一个对象 无菜单和控制栏   有视图

招考网对象的创建:CMainFrame对象在应用程序类的InitInstance函数中(即CMainFrame* pMainFrame = new CMainFrame;);CChildFrame对象是当新的子窗口被打开时,由应用程序框架来创建(MDI中InitInstance函数中ProcessShellCommand的调用用以创建子框架)。

招考网CMultiDocTemplate* pDocTemplate;

招考网pDocTemplate = new CMultiDocTemplate(

招考网IDR_TESTTYPE,

招考网RUNTIME_CLASS(CTestDoc),

招考网RUNTIME_CLASS(CChildFrame), // custom MDI child frame

招考网RUNTIME_CLASS(CTestView));

招考网AddDocTemplate(pDocTemplate);

招考网这里通过CDocTemplate(无论是SDI中的CSingleDocTemplate还是MDI中的CMultiDocTemplate)的构造

招考网函数,将文当、视图和框架(SDI中与主框架,MDI中与自框架)关联在一起了,形成了一个整体。

招考网使用CCreateContext类进行他们之间的关联,具体实现为:

招考网m_pAnotherView = new CAnotherView(); //new 一个新的视图,可以改为你新建的视图

招考网//获取一个已有的文档,可以是你新建的文档

招考网CDocument* m_pDoc = ((CFrameWnd*)m_pMainWnd)->GetActiveDocument();

  //文档和视图关联

  CCreateContext context;

  context.m_pCurrentDoc = m_pDoc;

  //创建视图

  UINT m_IDFORANOTHERVIEW = AFX_IDW_PANE_FIRST + 1; //创建视图的ID号,你可以自己设置

  CRect rect;

  m_pAnotherView->Create(NULL,NULL,WS_CHILD,rect,m_pMainWnd,m_IDFORANOTHERVIEW,&context);

招考网2.2 框架和视图的关联

招考网在第一部分分析我们知道,框架和视图其实都是windows窗口,不过框架提供了菜单、标题栏、状态栏等资源,而视图则只是一个矩形区域。MFC程序中视图决定大多数时候要依附于一个框架(SDI中的MainFrame和MDI中的子框架窗口),可以这样理解,框架相当于一个窗口容器(当然它本身也是一个windows窗口),而视图则正好是放置在框架内客户区域的内容。

招考网上面已经分析到,我们看到MFC的窗口实际上框架和视图的一个结合体,我们并不一定要提供文档、视图、框架的整个体系,我们只需要框架和视图的结合即可实现窗口的显示,这就要经过两个步骤实现:第一步将视图和框架关联,第二步显示框架(也就是一个windows窗口的显示)。以下给出框架和视图关联的具体实现:

  CChildFrame* pFrm = new CChildFrame();   //框架可以是你新建或者定制的框架类

  CCreateContext context;

  context.m_pNewViewClass = RUNTIME_CLASS(CDemoView); //视图可以是你想显示的视图

  pFrm->LoadFrame(IDR_TEST2TYPE,WS_CHILD |

  WS_OVERLAPPEDWINDOW,this,&context); //菜单资源你可以修改

  pFrm->ShowWindow(SW_SHOW);           //显示窗口

  pFrm->InitialUpdateFrame(NULL,true);        //调用视图的OnInitialUpdate()和框架的ActiveFrame(),你可以在这里设置窗口的标题

  当然你可以在这里添加视图和文档的关联,具体实现是添加以下代码:

  context.m_pCurrentDoc = m_pDoc;   // m_pDoc就是你要关联到的文档对象

 

 

触屏版 电脑版
3773考试网 琼ICP备12003406号-1