MFC 文档视图结构程序结构总揽

来源:互联网 发布:plulive直播软件 编辑:程序博客网 时间:2024/05/22 08:56
深入分析MFC文档视图结构(项目实践)

必备基础知识概述

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 )的主要组成:

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

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

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

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

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

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

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

除了侯捷先生在《深入浅出 MFC 中列出的以上的深入分析,我们还应该(很大程度上更加重要)掌握以下的关于 MFC SDI/MDI 的知识:

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

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

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

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

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

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

访问对象

访问位置

访问实现

应用程序 App

任何位置

① AfxGetApp();

② 在要使用应用程序 App 的文件中加入:

extern CAApp theApp ,然后直接使用全局的 theApp 变量。

主框架窗口

任何位置

① AfxGetMainWnd();

② AfxGetApp()->m_pMainWnd;

视图

框架类中

GetActiveView();// 当前的活动视图

文档类中

GetFirstViewPosition (); // 可以获取全部视图

GetNextView ();

文档

文档类中

GetDocument() 

文当模版类中

GetFirstDocPosition(); // 该文档模版对应全部文档

GetNextDoc();

框架类中

GetActiveDocument(); // 当前活动文当

子框架类( MDI中)

主框架类中

① MDIGetActive ();

② GetActiveFrame ();

视图类中

GetParentFrame();

文档模版

文档类中

GetDocTemplate();

应用程序 App 中

GetFirstDocTemplatePosition();

GetNextDocTemplate();

说明: 1 )以上给出的都是方法,实际访问中可能还要进行以下简单的处理,如类型转换,循环遍历等;

)可能没有列举完所有可能位置的互访问,但可以通过他们的组合得到。

文档、视图、框架之间的关联

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

2.1 文档和视图间的关联

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

SDI 

CSingleDocTemplate* pDocTemplate;

pDocTemplate = new CSingleDocTemplate(

IDR_MAINFRAME,

RUNTIME_CLASS(CTestDoc),

RUNTIME_CLASS(CMainFrame),// main SDI frame window

RUNTIME_CLASS(CTestView));

AddDocTemplate(pDocTemplate);

MDI 

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 中与自框架)关联在一起了,形成了一个整体。

 

手工实现文当和视图的关联

在实际的项目开发时候仅仅依靠 MFC AppWizard 生成的文当和视图、框架是不够的,因此我们需要掌握手工进行这种关联。手工进行文当和视图的关联可以有以下两种实现方式:

模仿 MFC AppWizard 实现,使用 CDocTemplate 的构造函数:在上面的分

析中我们可以看到通过 CDocTemplate (无论是 SDI 中的 CSingleDocTemplate 还是 MDI 中的 CMultiDocTemplate )的构造函数我们可以获得文档、视图和框架的关联。因此可以通过模拟这种方式进行关联。具体实现方法如下:

) 创建新的文档、视图和框架类,方法是使用 VC 中的 Insert MFC Class

实现。注意到框架类选择 CMDIChildWnd 作为基类,文档类选择 CDocument 作为基类,而视图类则可以根据需要选择 CView 或其子类( CEditView )等作为基类。

) 为该框架添加菜单资源,方法是在 VC 资源窗口 Menu 菜单下添加新的菜

单,当然可以通过复制 VC 提供默认菜单进行修改。

) 在 App 类的 InitInstance ()中添加如下类似代码:

CMultiDocTemplate* m_pDocTemplate;

m_pDocTemplate = new CMultiDocTemplate(

IDR_TESTTYPE,// 改为你新建的菜单资源 ID

RUNTIME_CLASS(CTestDoc),// 改为你新建的文档类

RUNTIME_CLASS(CChildFrame), // 改为你新建的框架类

RUNTIME_CLASS(CTestView));// 改为你新建的视图类

AddDocTemplate(m_pDocTemplate);

) 为了记录这个文档模版,你可以在 App 类中添加一个 CMultiDocTemplate*

类型变量来维持这个文档模版。

上面给出了通过 CDocTemplate 的构造函数将文档、视图、和框架关联起来,但

是有时候我们并不想创建一个新的文档模版,我们只是想给同一个数据提供不同的结果显示,或者说是为同一个文档添加一个新的视图,并提供他们之间的一个切换。还有一种可能就是我们本来不是一个文档视图结构支持的程序,想为视图添加一个文档,更好进行业务逻辑和表示层的一个分离。第一种方法的实现方法:

Step 1 :使用 VC 6.0 新建一个 Project ,命名为: MultiView 。除选择单文档属性外,一切使用“默认”方式。于是你可以获得五个类:CMainFrame , CMultiViewApp , CMultiViewDoc , CMultiViewView ,和 CAboutDlg 

 

Step 2 :新建一个新的视图 View ,添加一个新的 MFC Class ( Insert - >New Class ),基类为 CView (或者 CView 的派生子类,如CEditView 等)。类的名字为 CAnotherView ,这就是新的视图;并为 CAnotherView 添加 GetDocument 的实现:

CMultiViewDoc* CAnotherView::GetDocument()

{

return (CMultiViewDoc*)m_pDocument;

}

 

Step 3 :在 CMultiViewApp 添加成员变量记录这两个视图:

private:

CView* m_pFirstView;

CView* m_pAnotherView;

给程序菜单 IDR_MAINFRAME 添加一个菜单项目“视图”,该菜单项有两个子菜单“视图一”和“视图二”,添加相应函数( void CMultiViewApp:: OnShowFirstview ()和 void CMultiViewApp :: OnShowSecondview ());

 

Step 4 :创建新的视图:在 BOOL CMultiViewApp :: InitInstance () 中添加代码:

…….

// 创建一个新的视图

CView* m_pActiveView = ((CFrameWnd*)m_pMainWnd)->GetActiveView();

m_pFirstView = m_pActiveView;

m_pAnotherView = new CAnotherView();

 

// 文档和视图关联

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

 

CCreateContext context;

context.m_pCurrentDoc = m_pDoc;

 

// 创建视图

UINT m_IDFORANOTHERVIEW = AFX_IDW_PANE_FIRST + 1;

CRect rect;

m_pAnotherView->Create(NULL,NULL,WS_CHILD,rect,m_pMainWnd,

m_IDFORANOTHERVIEW,&context);

    ……

 

Step 5 :现在已经创建了视图,并且都和文档关联起来了。现在要作的就是视图间的转换。在 void CMultiViewApp :: OnShowFirstview ()中添加实现代码:

void CMultiViewApp::OnShowFirstview()

{

// TODO: Add your command handler code here

UINT temp = ::GetWindowLong(m_pAnotherView->m_hWnd, GWL_ID);

    ::SetWindowLong(m_pAnotherView->m_hWnd, GWL_ID, ::GetWindowLong(m_pFirstView->m_hWnd, GWL_ID));

    ::SetWindowLong(m_pFirstView->m_hWnd, GWL_ID, temp);

 

m_pAnotherView->ShowWindow(SW_HIDE);

m_pFirstView->ShowWindow(SW_SHOW);

 

((CFrameWnd*)m_pMainWnd)->SetActiveView(m_pFirstView); 

((CFrameWnd*) m_pMainWnd)->RecalcLayout();

    m_pFirstView->Invalidate();

}

 

在 void CMultiViewApp :: OnShowSecondview ()中添加实现代码:

void CMultiViewApp::OnShowSecondview()

{

// TODO: Add your command handler code here

UINT temp = ::GetWindowLong(m_pAnotherView->m_hWnd, GWL_ID);

    ::SetWindowLong(m_pAnotherView->m_hWnd, GWL_ID, ::GetWindowLong(m_pFirstView->m_hWnd, GWL_ID));

    ::SetWindowLong(m_pFirstView->m_hWnd, GWL_ID, temp);

 

m_pFirstView->ShowWindow(SW_HIDE);

m_pAnotherView->ShowWindow(SW_SHOW); 

 

((CFrameWnd*)m_pMainWnd)->SetActiveView(m_pAnotherView); 

((CFrameWnd*) m_pMainWnd)->RecalcLayout();

    m_pAnotherView->Invalidate();

}

 

Step 6 :为了演示,这里将不同的视图给予一个标记,在 CMultiViewView 和 CAnotherView 的 OnDraw 方法中分别添加以下代码:

pDC->TextOut(400,300,"First View");

pDC->TextOut(400,320,pDoc->GetTitle());

pDC->TextOut(400,300,"Another View");

pDC->TextOut(400,320,pDoc->GetTitle());

 

至此就大功告成了,但是实现过程中有 几 点说明:

1)   实现中由于使用到相关的类,因此在必要的地方要 include 相关的头文件,这里省略; CAnotherView 的默认构造函数是 Protected 的,需要将其改为 Public ,或者提供一个产生 CAnotherView 对象的方法(因要创建视图对象);

2)   这里给出的是一个示例代码,实际开发中可以通过参考实现获得自己想要实现的具体应用情况(例如视图类的不同、数量不同,更重要的还有业务逻辑的不同实现等);

第二种视图和文档关联的方法:我们使用 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 AppWizard 实现,使用 CDocTemplate 的构造函数实现,即和 2.1 中文档和视图间的关联方式相同,这里就不再给出,参看上面的详细实现即可。

同上面的分析,在很多的时候我们并不是需要提供一个新的文档模版,我们只是需要显示一个新的窗口( MDI 程序),例如我们在作 MIS 系统界面管理的时候,经常出现的情况就是用户点击一个菜单选项,即弹出一个处理窗口。而要显示一个新的窗口,我们可以通过 CDocTemplate 的 OpenDocumentFile()方法打开一个文档实现,这样就建立一套的文档、视图和框架的体系。上面已经分析到,我们看到 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 就是你要关联到的文档对象

代码实例

本部分将以一个通用的 MDI 项目界面设计开发为例,将上面的分析附诸实践。

3.1 情景描述

一个常见界面逻辑为:用户打开一个系统,显示基本的菜单,用于用户的登录、注销和用户管理(当然这也可以通过一个用户登录的对话框实现)。用户正确登录后,显示系统的功能操作界面,当用户点击一个菜单项后(对应一个或者多个业务逻辑),弹出一个处理操作界面(并非对话框)。各个功能操作界面可共存于一个框架内,可以最大化、最小化或者关闭。

3.2 代码实现

下面就将上面的提到的情景用前面提到的技术,给出详细的实现方案。

Step 1 :新建一个 MFC 项目,名称为 Demo ,选择不用 Document/View Architecture 支持(第二步去掉默认的复选框即可)。这样系统为你默认生成 5个类: CDemoApp 、 CMainFrame 、 CChildFrame 、 CAboutDlg 、 CDemoView 。各个类的含义上面已经分析了,不罗嗦。另外系统还提供了两个默认的菜单: IDR_DEMOTYPE 和 IDR_MAINFRAME ,将 IDR_MAINFRAME 的菜单的“文件”改名为“开始”(好像更加专业,不该也没有什么,本来就是 Demo ),然后将这个菜单项的子菜单中改为“登录”、“注销”,并使用默认的子项,并将前两者的 ID 号改为:“ ID_LOGIN ”和“ ID_LOGOUT ”。拷贝( Ctrl + C )粘贴( Ctrl + V ),则得到一个名称为 IDR_MAINFRAME1 的菜单资源,删除原有的 IDR_DEMOTYPE 菜单(注一先保存名称),再将IDR_MAINFRAME1 的名称改为 IDR_DEMOTYPE 。再为 IDR_DEMOTYPE 添加一个菜单项“功能”,添加两个子菜单项“业务逻辑一”和“业务逻辑二”, ID号分别为: ID_FUNC_ONE 和 ID_FUNC_TWO 。

Step 2 :给 CDemoApp 添加两个变量,保存菜单资源:

HMENU m_hOPMenu;

HMENU m_hInitMenu;

并在 BOOL CDemoApp::InitInstance()中添加代码:

 

m_hInitMenu = ::LoadMenu(hInst, MAKEINTRESOURCE(IDR_MAINFRAME));

m_hOPMenu = ::LoadMenu(hInst, MAKEINTRESOURCE(IDR_DEMOTYPE));

为了显示效果,在 BOOL CDemoApp::InitInstance()中添加代码:

 

pFrame->SetWindowText(" 未登录 ");

m_nCmdShow = SW_SHOWMAXIMIZED;

pFrame->ShowWindow(m_nCmdShow);// 系统提供

pFrame->UpdateWindow();

为菜单项“登录”添加响应函数(使用 Class Wizard , Class Name 选择 CDemoApp )

 

void CDemoApp::OnLogin()

{

// TODO: Add your command handler code here

SetMenu(AfxGetApp()->m_pMainWnd->m_hWnd,m_hOPMenu);

AfxGetApp()->m_pMainWnd->SetWindowText(" 已登录 ");

}

同上,为菜单项“注销”添加响应函数:

 

void CDemoApp::OnLogout()

{

// TODO: Add your command handler code here

if(((CMainFrame *)AfxGetMainWnd())->m_pFuncOneFrame != NULL)

((CMainFrame *)AfxGetMainWnd())->m_pFuncOneFrame->SendMessage(WM_CLOSE);

 

if(((CMainFrame *)AfxGetMainWnd())->m_pFuncTwoFrame != NULL)

((CMainFrame *)AfxGetMainWnd())->m_pFuncTwoFrame->SendMessage(WM_CLOSE);

 

SetMenu(AfxGetApp()->m_pMainWnd->m_hWnd,m_hInitMenu);

 

AfxGetApp()->m_pMainWnd->SetWindowText(" 未登录 ");

}

这就实现了登录和注销的功能(当然实际中可能还会有一个验证用户权限和合法性的对话框,这里从略),并实现了登录注销时刻用户操作菜单的转变。注意:这里 OnLogout中前两行代码是在注销的时候要把已经打开的窗口关闭而添加的, m_pFuncOneFrame和 m_pFuncTwoFrame的定义和作用请参见后面定义。

Step 3 :添加一个新的子框架类 CDemoFrame ,其基类为 CMDIChildWnd 。添加一个两个新的视图类 CFuncOneView 和 CFuncTwoView 类,前者的基类为 CView ,后者为 CFormView 。当然为了添加 CFuncTwoView 类,需要先 Insert 一个对话框资源,并将 ID 改为 IDD_FUNC_TWO_DLG ,属性 Style 修改为“ child ”(默认为 Popup )。这样在新建 CFuncTwoView 的时候选择该 DialogID 为 IDD_FUNC_TWO_DLG 。注意将 CDemoFrame 的构造函数改为public (默认是 protected )。

Step 4 :为 CMainFrame 添加两个成员变量记录各个业务逻辑对应的窗口,在 MainFrm.h 中添加:

CDemoFrame* m_pFuncOneFrame;

CDemoFrame * m_pFuncTwoFrame;

并在 CMainFrame::CMainFrame() 中初始化:

CMainFrame::CMainFrame()

{

// TODO: add member initialization code here

m_pFuncOneFrame = NULL;

m_pFuncTwoFrame = NULL;

}

Step 5 :为“业务逻辑一”添加响应函数( CMianFrame 中):

 

void CMainFrame::OnFuncOne()

{

// TODO: Add your command handler code here

if (m_pFuncOneFrame != NULL)

{

m_pFuncOneFrame->MDIActivate();

 

return ;

}

 

m_pFuncOneFrame = new CDemoFrame();

 

CCreateContext context;

context.m_pNewViewClass = RUNTIME_CLASS(CFuncOneView);

 

m_pFuncOneFrame->LoadFrame(IDR_MAINFRAME, WS_MAXIMIZEWS_OVERLAPPEDWINDOW, this, &context);

 

m_pFuncOneFrame->SetWindowText(" 业务逻辑一 ");

m_pFuncOneFrame->ShowWindow(SW_SHOWMAXIMIZED);

m_pFuncOneFrame->InitialUpdateFrame(NULL,true);

}

同上,为“业务逻辑二”添加响应函数:

 

void CMainFrame::OnFuncTwo()

{

// TODO: Add your command handler code here

if (m_pFuncTwoFrame != NULL)

{

m_pFuncTwoFrame->MDIActivate();

 

return ;

}

 

m_pFuncTwoFrame = new CDemoFrame();

 

CCreateContext context;

context.m_pNewViewClass = RUNTIME_CLASS(CFuncTwoView);

 

m_pFuncTwoFrame->LoadFrame(IDR_MAINFRAME, WS_MAXIMIZEWS_OVERLAPPEDWINDOW, this, &context);

 

m_pFuncTwoFrame->SetWindowText(" 业务逻辑二 ");

m_pFuncTwoFrame->ShowWindow(SW_SHOWMAXIMIZED);

m_pFuncTwoFrame->InitialUpdateFrame(NULL,true);

}

这样,上述的需求情景基本是做到了,但是需要说明的是:

) 需要在适当的地方加入适当的头文件,就是说在使用类的时候要 include 其实现的头文件。

) 上面其实是很多的 MIS 管理系统的通用界面操作模版,大家可以在实际的项目开发中作相应的修改(主要是实现相应的业务逻辑等);

) 这里提供的默认的主框架窗口比较简单(默认);

) 上面的例子中,是让其生成不支持 MFC Document/View Architecture ,如果已经有了默认的支持 MFC Document/View Architecture 的程序,请将 App 中模仿上面的实现即可。

) 上面可以使用 MFC AppWizard 生成的 CChildFrame 类代替 CDemoFrame 类,但是建议新建框架类,业务逻辑一和业务逻辑二可以使用不同的框架类,模仿实现即可。

当然,你肯能需要为视图添加文档以实现业务逻辑和表现层的松耦合,下面就为 CFuncOneView添加文档视图结构支持。

Step 6 :添加一个文档类 CDemoDoc ,基类为 CDocument 并将 CDemoDoc 的构造函数改为 public (默认为 protected ),为了演示,为 CDemoDoc添加函数 GetData ():

CString CDemoDoc::GetData()

{

return "Hello world";

}

Step 7 :为 CFuncOneView添加函数 GetDocument :

CDemoDoc* CFuncOneView::GetDocument()

{

return (CDemoDoc*)m_pDocument;

}

并修改 OnDraw 函数:

void CFuncOneView::OnDraw(CDC* pDC)

{

//CDocument* pDoc = GetDocument();

// TODO: add draw code here

CDemoDoc* pDoc = GetDocument();

 

pDC->TextOut(50,50,pDoc->GetData());

}

Step 8 :将 CDemoDoc 和 CFuncTwoView 关联:修改 void CMainFrame::OnFuncOne()函数为:

 

void CMainFrame::OnFuncOne()

{

// TODO: Add your command handler code here

if (m_pFuncOneFrame != NULL)

{

m_pFuncOneFrame->MDIActivate();

 

return ;

}

 

m_pFuncOneFrame = new CDemoFrame();

 

CDemoDoc* m_pDoc = new CDemoDoc();

 

CCreateContext context;

context.m_pNewViewClass = RUNTIME_CLASS(CFuncOneView);

 

context.m_pCurrentDoc = m_pDoc;

 

m_pFuncOneFrame->LoadFrame(IDR_MAINFRAME, WS_MAXIMIZEWS_OVERLAPPEDWINDOW, this, &context);

 

m_pFuncOneFrame->SetWindowText(" 业务逻辑一 ");

m_pFuncOneFrame->ShowWindow(SW_SHOWMAXIMIZED);

m_pFuncOneFrame->InitialUpdateFrame(NULL,true);

}

至此,就完成了整个过程。需要说明的是:

) 需要在适当的地方加入适当的头文件,就是说在使用类的时候要 include 其实现的头文件。

) 如果是已经有了文档视图支持的程序,上面的文档可以使用系统中提供的文档;

上面提供了一个简单通用的界面操作的实现,大家可以参照实现,例如添加更多的视图、实现自己的业务逻辑等。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 主板与cpu不兼容怎么办 cpu跟主板不兼容怎么办 软件与电脑不兼容怎么办 win8系统无限重启怎么办 安装微信旧版本登录提示升级怎么办 手机软件与系统不兼容怎么办 下载旧版本微信闪退登陆不了怎么办 企业微信一直登录失败怎么办 360浏览器9.1经常卡死怎么办 手机版爱奇艺看电影屏幕变小怎么办 找不到旧版本米聊怎么办 苹果id被锁了怎么办 新浪微博支付宝解绑失败怎么办 阿里妈妈升级看不到引流人数怎么办 阿里妈妈账号被冻结怎么办 微博昵称到次数怎么办 五星好评之后忘记截图了怎么办 评价后忘了截图怎么办 好评率太低不能买东西了怎么办 淘宝评价被删了怎么办 淘宝店铺有流量没有成交怎么办 淘宝好评被删了怎么办 淘宝评论被系统删除怎么办 淘宝被商家删除评价怎么办 淘宝评价管理商家删除了怎么办 淘宝商家删除评价我该怎么办 我的评价隐藏了怎么办 淘宝把评论删了怎么办 淘宝虚假交易被删除评价怎么办 淘宝好评评错了怎么办 被淘宝骗了好评怎么办 美团好评被删了怎么办 卖家收到好评内容是差评怎么办 淘宝收货电话写错了怎么办 淘宝评价写错了怎么办 饿了么商家差评怎么办 淘宝不给补差价怎么办 淘宝顾客给差评怎么办 淘宝买家账号体检违规怎么办 买家淘宝账户体检中心违规怎么办 淘宝卖家电话骚扰该怎么办