在应用程序的开发中,有些用户可能需要解决这样一个问题:对于某类型的一个文档需要用不同的视图显示并且处理,来实现对文档的多视图操作。笔者也曾经开发过此类型的应用程序。但笔者在参考了一些关于这方面的书籍以后,感觉到关于一个文档创建多个视图的实现方法写的比较少,有些参考书虽然提到了,但是其中的内容不够具体,参照实现起来比较困难。这里,笔者介绍一种Visual
C++ 5.0环境下一个文档创建多个视图的易于实现的方法,供读者参考(以三个视图为例)。
下面是实现步骤:
创建新项目
运行Microsoft开发者工作室New选项,用MFC AppWizard(.exe)创建一个新的Project(项目),取名为Demo。
笔者在这里创建的是基于多文档的(MDI)应用程序,所以在创建项目时,在MFCAppWizard
Step1窗口中要设置Multiple documents选项。这样,项目Demo编译连接以后生成Demo.exe。运行的结果是:每次打开一个文档就会显示一个视图。如果要创建基于单文档的(SDI)应用程序,可以设置Single
document选项。现在项目Demo中已经包含了下面几个类:
增加项目Demo中的类
打开项目Demo,选择View菜单中的ClassWizard(类向导)的选项,用类向导对话框中的Addclass
下的New选项增加下面几个新类到项目中,分别是CFirstView、CSecondView、CFirstFrame和CSecondFrame。
CFirstView、CSecondView的基础类笔者选择的是CView,CFirstFrame、CSecondFrame的基础类是CMDIChildWnd。这样项目Demo中就多了下面几个类:
编辑Demo.h文件
需要建立三个文档模板,分别对应三个视图。因为文档模板提供了MFC用来将文档、视、框架结合在一起的框架结构。这里的文档模板是用于MDI应用程序的CMultiDocTemplate(用于SDI应用程序的是CSingleDocTemplate),因此要在类CDemoApp声明中增加三个公有型的成员变量:
class CDemoApp:public CWinApp
{
public:
CDemoApp();
CMultiDocTemplate *pDocTemplate;
CMultiDocTemplate *pFirstTemplate;
CMultiDocTemplate *pSecondTemplate;
∥Overrides
....
DECLARE_MESSAGE_MAP()
};
编辑Demo.cpp文件
首先,在Demo.cpp的头部增加四条#include指令:
#include “FirstFrame.h”
#include “SecondFrame.h”
#include “FirstView.h”
#include “SecondView.h”
然后,需要在应用程序的模板列表中增加两个文档模板。需要将新增的两个视图与文档CDemoDoc对应起来,同时新增的两个视图要分别使用新增的MDI子窗口CFirstFrame和CSecondFrame,在CDemoApp::
InitInstance中作如下修改:
pDocTemplate=newCMultiDocTemplate(
IDR_DEMOTYPE,
RUNTIME_CLASS(CDemoDoc),
RUNTIME_CLASS(CChildFrame),
∥用户自定义MDI子窗口框架
RUNTIME_CLASS(CDemoView));
AddDocTemplate(pDocTemplate);
pFirstTemplate=newCMultiDocTemplate(
IDR_DEMOTYPE,
RUNTIME_CLASS(CDemoDoc),
RUNTIME_CLASS(CFirstFrame),
∥用户自定义MDI子窗口框架
RUNTIME_CLASS(CFirstView));
AddDocTemplate(pFirstTemplate);
pSecondTemplate=newCMultiDocTemplate(
IDR_DEMOTYPE,
RUNTIME_CLASS(CDemoDoc),
RUNTIME_CLASS(CSecondFrame),
∥用户自定义MDI子窗口框架
RUNTIME_CLASS(CSecondView));
AddDocTemplate(pSecondTemplate);
编辑类CFirstView和类CSecondView
首先,加入下列成员变量:
pubilc:
CDemoDoc *GetDocument();
到FirsView.h和SecondView.h。
接着,对FirstView.cpp用如下修改:
void CFirstView::OnDraw(CDC *oDC)
{
CDemoDoc *pDoc=GetDocument();
∥TODO:add draw code here
}
....
#ifdef _DEBUG
.....
CDemoDoc *CFirstView::GetDocunent()
{
ASSERT(m_pDocument→IsKindOf
(RUNTIME_CLASS(CDemoDoc)));
return(CDenidDoc *)m_pDocument;
}
#endif ∥_DEBUG
然后,加入下列代码到SecondView.cpp中:
void CSecondView::OnDraw(CDC *pDC)
{
CDemoDoc *pDoc=GetDocument();
∥TODO:add draw code here
}
...
#ifdef _DEBUG
....
CDemoDoc *CSecondView::GetDocument()
{
ASSERT(m_pDocument→IsKindOf(RUNTIME_CLASS(CDemoDoc)));
return(CDemodDoc *)m_pDocument;
}
#endif ∥_DEBUG
现在,在CFirstView.cpp,CSecondView.cpp的开头分别加入下面一条#include指令:
#include “DemoDoc.h”
编辑DemoDoc.h文件
由于一个文档创建三个视图,即文档要使用三个MDI子窗口,因此首先要在类CDemoDoc的声明中增加三个公有型的成员变量:
class CDemoDoc:public CDocument
{
....
∥Attributes
public:
CChildFrame *pChildFrame;
CFirstFrame *pFirstFrame;
CSecondFrame *pSecondFrame;
∥Operations
....
DECLARE_MESSAGE_MAP()
};
同时,在DemoDoc.h的头部增加三条#include 指令:
#include “ChildFrm.h”
#include “FirstFrame.h”
#include “SecondFrame.h”
编辑CDemoView::OnInitialUpdate
应用程序打开一个现有的文档,为了打开另外新增的两个视,就需要调用文档模板的CreateFrame()成员。另外两个新增的文档模板将文档类型和两个新增的视类联系起来,因此,在OnInitialUpdate中增加下列代码:
vokd CDemoView::OnInitialUpdate()
{
CView::OnInitialUpadate()
...
CDemoDoc *pDoc=GetDocument();
ASSERT_VALID(pDoc);
CMainFrame *pAppFrame=(CMainFrame *)
AfxGetApp()→m_pMainWnd;
ASSERT_KINDOF(CMainFrame,pAppFrame);
pDoc→pChildFrame=(CChildFrame *)GetParentFrame();
CMultiDocTemplat *pFirstTemplate=((CDemoApp *)AfxGetApp())→pFirstTemplate;
ASSERT_VALID(pFirstTemplate);
pDoc→pFirstFrame=(CFirstFrame *)pFirstTemplate→CreateNewFrame(pDoc,pAppFrame);
pFirstTemplate→InitialUpdateFrame(pDoc→pFirstFrame,pDoc);
CMultiDocTemplate *pSecondTemplate=((CDemoApp *)AfxGetApp())→pSecondTemplate;
ASSERT_VALID(pSecondTemplate);
pDoc→pSecondFrame=(CSecondFrame *)pSecondFrame→CreateNewFrame(pDoc,pAppFrame);
pSecondTemplate→InitialUpdateFrame(pDoc→pSecondFrame,pDoc);
}
调用InitialUpdateFrame()函数,是对视图的窗口框架进行初始化。而后,在文件DemoView.cpp的开头,增加如下七条#include指令:
#include “Windows.h”
#include “Windowsx.h”
#include “MainFrm.h”
#include “FirstFrame.h”
#include “SecondFrame.h”
#include “FirstView.h”
#include “SecondView.h”
修改串资源
由于有三个文档模板,为了防止工作框认为有多个文档类型,需要对IDR_DEMOTYPE的Caption(标题)进行修改。将“\n\Demo\nDemo\n\n\n\Demo.Document\nDemoDocument”
改成
“\n\Demo\n\n\n\n\Demo.Document\nDemoDocument”。
经过上述几个步骤以后,就可以实现一个文档创建多个视图。最后的事情就是进行编译连接。对于上述的实现方法有兴趣的读者不防一试。