使用VC++实现单文档多视图的一种方法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
使用VC++实现单文档多视的程序框架
91550部队指控中心池晓春赵鹤群
摘要:本文分析了在对同一数据源使用多种形式显示的情况下,采用单文档多视的程序框架开发显示软件的原因,介绍了单文档多视框架(SDMV)的实现方法,并在Windows 2000环境下,使用Visual C++ 6.0创建开发单文档多视框架的示例程序。
关键词:单文档多视(SDMV)视图切换
1选择SDMV程序框架的原因
程序员使用Visual C++ 6.0开发软件时,为了缩短开发时间和工作量,通常借助AppWizard生成基于MFC的SDI或MDI应用程序框架。但是要实现对同一数据源使用多种形式显示的功能,使用SDI或MDI的框架进行软件开发都有各自的缺陷,不能较好的满足软件需求,这是因为:
使用SDI框架的应用程序具有单一文档和单一视图,即程序运行时只能够生成一个文档类对象和一个视图类对象,虽然满足使用同一数据的要求,但是由于只有一个视图窗口,无法实现以多种形式显示试验数据。
使用MDI框架的应用程序具有多窗口的特点,可以使用多个子窗口来实现对不同数据源的浏览,但它的视图和文档一一对应,即视图+文档构成一个子窗口。由于各个子窗口之间数据相互独立,如果要保持数据同步更新就需要采用特殊的技术,所以对于用户在程序各个窗口之间对同一数据源进行不同形式的浏览,用这种方式实现起来既费时又费力。
由于SDI和MDI这两种Windows标准应用程序框架不能满足软件开发的需要,就特别需要一种被称为“单文档多视”的应用程序框架。顾名思义,该框架用单一的文档类来统一管理应用程序的所有数据,同时用多个视图以多种显示形式(如:表格、曲线、趋势图)等来显示这些数据。程序在任何时刻都可以用同一个窗口,通过切换视图的方法以不同的形式显示同一数据。可以看出,使用SDMV程序框架开发数据显示软件,就能够更好的满足用户的需求。
2SDMV程序框架的实现方法
SDMV程序框架的本质是文档-视图结构,它针对同一数据源使用不同的形式在多个视图中显示。如果数据发生改变,所有和数据相关的视图中的显示内容也会随之改变来反映数据的变化。针对这种特点,可以考虑通过改造SDI框架来实现SDMV框架,借助VC ++提供的AppWizard生成SDI应用程序框架,可以在很大程度上减少工作量,
缩短开发时间。
SDI框架提供了单一的文档类和视图类,在程序运行时会生成单一的文档类对象和视图类对象。为SDI框架增加视图类对象,把新增的视图类对象关联到原有的文档类对象上,并提供多视图的切换机制和更新机制,进而实现单文档多视的程序框架。
视图切换机制是实现SDMV框架的一个关键。程序启动时生成一个文档类对象和一个活动的视图类对象。在用户下达视图切换命令以后,首先检查用户选择的是否是当前视图类对象,如果是,程序不做处理;否则,对视图类对象列表进行检索。如果该对象已经存在,则把它置为当前活动状态,把原来的视图类对象置为隐藏状态;如果该对象不存在,则创建该对象,把它关联到文档类对象上,并该对象置为当前活动状态,把原来的视图类对象置为隐藏状态。
在该程序框架中,所有相关数据都存储在文档类对象里。一旦文档类对象里的数据发生变化,对应的多个视图也必须通过更新显示来反映数据的变化。考虑到用户使用单一视图并可以自由切换,制定这样的视图更新机制:文档类对象里的数据发生改变,只更新用户使用的当前视图的显示内容,如果用户切换到其它视图,则在目标视图成为当前视图后更新其显示内容。与同时更新所有视图相比,这样做在很大程度上提高了视图更新的效率,缩短了程序响应时间。
3建立SDMV程序框架的例程
下面用一个简单的例子来介绍SDMV框架的开发过程,在实际工程中可以根据具体的需求为该框架增加更多的功能。
1)使用VC++ 6.0建立一个基于SDI程序框架的名为Demo的工程。
2)使用ClassWizard为工程添加两个新的派生于CView的名为CFirstView和
CSecondView的类。
注意:把CFirstView和CSecondView的类构造函数属性从protected改为
public,供生成类对象时调用。
3)在IDR_MAINFRAME菜单资源中的“查看”菜单中添加下面两项。
使用ClassWizard添加命令处理函数到CMainFrame类中。
4)为CMainFrame类添加辅助函数SwitchToView,用于完成视图切换工作。
在CMainFrame类的头文件中添加辅助函数用到的枚举类型enum eView={FIRST=1, SECOND=2};
void CMainFrame::SwitchToView(eView nView)
{
CView* pOldActiveView = GetActiveView();
CView* pNewActiveView = (CView*)GetDlgItem(nView);
if (!pNewActiveView) {
switch (nView) {
case FIRST :
pNewActiveView = (CView*)new CFirstView;
break;
case SECOND :
pNewActiveView = (CView*)new CSecondView;
break;
}
CCreateContext context;
cont ext.m_pCu rre ntD oc = p Old Act ive Vie w->Get Doc ume nt();
pNewActiveView->Create(NULL, NULL, WS_BORDER, CFrameWnd::rectDefault, this, nView, &context);
pNewActiveView->OnInitialUpdate();
}
SetActiveView(pNewActiveView);
pNewActiveView->ShowWindow(SW_SHOW);
pOldActiveView->ShowWindow(SW_HIDE);
if (pOldActiveView->GetRuntimeClass() ==
RUNTIME_CLASS(CFirstView))
pOldActiveView->SetDlgCtrlID(FIRST);
else if (pOldActiveView->GetRuntimeClass() == RUNTIME_CLASS(CSecondView))
pOldActiveView->SetDlgCtrlID(SECOND);