使用VC++实现单文档多视图的一种方法

合集下载

第八章 VC++文档和视图

第八章 VC++文档和视图

第8章文档和视图精讲MFC应用程序的核心是文档/视图结构。

在前面章节的学习中,已经接触了不少文档/视图结构的应用程序,本章将详细分析其结构和原理,并进一步学习使用复杂的文档结构、构造更加丰富的视图。

8.1 文档/视图概述使用MFC的AppWizard可以创建三种类型的应用程序:(1)单文档界面的应用程序(SDI:Single Document Interface)(2)多文档界面的应用程序(MDI:Multiple Documents Interface)(3)基于对话框的应用程序(Dialog based)基于对话框的应用程序框架非常简单,由应用程序类、对话框类构成。

通过应用程序类的InitInstance()函数,构造一个模式对话框对象;调用DoModal()函数,让Windows对话框处理程序象通常情况一样接受和分配消息;用户退出对话框后,程序也就结束了。

我们已经知道SDI应用程序由应用程序类(CWinApp)、框架窗口类(CFrameWnd)、文档类(CDocument)、视图类(CView)和文档模板类(CSingleDocTemplate)共同作用。

MDI应用程序与SDI 应用程序的主要差别在于:MDI有CMDIFrameWnd和CMDIChildWnd两个框架窗口类,前一个派生CMainFrame类,负责菜单等界面元素的主框架窗口管理;后一个派生CChildFrame类,负责相应的文档及其视图的子框架维护。

而SDI由框架窗口类CFrameWnd 派生CMainFrame类。

一个文档可以有多个视图,但一个视图只能对应一个确定的文档。

因此,MDI应用程序需要解决的问题是多个文档的数据管理方法。

在MDI应用程序中,文档模板只支持主窗口。

每打开一个新文档时,都调用文档类的成员函数OnNewDocument(),建立一个由CMDIChildWnd派生的新的MDI子窗口,在子窗口中保存已打开的文档,所有这些细节都由MFC库来处理。

用VC++MFC做文本编辑器(单文档模式)

用VC++MFC做文本编辑器(单文档模式)

用VC++MFC做文本编辑器(单文档模式)原来做过一个用对话框实现的文本编辑器,其实用MFC模板里面的单文档模板也可以做,甚至更加方便,适合入门级的爱好者试试,现介绍方法如下:1,首先新建一个工程,选择MFC AppWizard(exe),定名字为:textview_1,程序类型选择单个文档,其他均默认完成。

2,在系统自动生成的CTextview_1Doc类里面增加一个控件,用于文本文档的暂时存放:class CTextview_1Doc : public CDocument{......public:CStringArray m_strContent;}然后在CTextview_1Doc类的Serialize函数里面增加打开、保存文本文件的程序:void CTextview_1Doc::Serialize(CArchive& ar){CString str;if (ar.IsStoring()){// TODO: add storing code hereint nLines = (int)m_strContent.GetSize();for ( int i=0; i<nLines; i++ ){str = m_strContent.GetAt( i );ar.WriteString( str ); // 将字符串集合类对象中文本保存到硬盘}}else{// TODO: add loading code herewhile ( ar.ReadString( str ) ){m_strContent.Add( str ); // 将行文本添加到字符串集合类对象中}}}然后鼠标在CTextview_1Doc 上点击右键,在弹出菜单里面选择:Add Virtual Function,在弹出的窗口中选中DeleteContents,点击“添加和编辑”按钮。

在生成的程序中添加以下代码:void CTextview_1Doc::DeleteContents(){// TODO: Add your specialized code here and/or call the base classm_strContent.RemoveAll(); // 清除集合类对象中的内容CDocument::DeleteContents();}3,在系统自动生成的CTextview_1View类里面增加一个编辑器的控件指针成员,用于在界面中生成文本编辑器:class CTextview_1View : public CView{......public:CEdit* m_ctrlEdit;}该指针成员在类建立时要设置初始化值为NULL,否则运行起来就会出错,如下:CTextview_1View::CTextview_1View(): m_ctrlEdit(NULL) //添加这一行初始化代码{// TODO: add construction code here}用第2点介绍的类似步骤,为CTextview_1View类重写其OnInitialUpdate函数,添加内容如下:void CTextview_1View::OnInitialUpdate(){CView::OnInitialUpdate();// TODO: Add your specialized code here and/or call the base classCRect rcClient;GetClientRect( rcClient ); // 获取当前视图的客户区大小// if ( m_ctrlEdit ) delete m_ctrlEdit;m_ctrlEdit = new CEdit();m_ctrlEdit->Create( ES_MULTILINE | WS_CHILD | WS_VISIBLE| WS_HSCROLL | ES_AUTOHSCROLL // 自动水平滚动| WS_VSCROLL | ES_AUTOVSCROLL , // 自动垂直滚动rcClient, this, 201); // 创建多行编辑控件CTextview_1Doc* pDoc = GetDocument(); // 获取与视图相关联的文档指针// 以下是将文档中的m_strContent内容全部赋给strCString str;int nLines = (int)pDoc->m_strContent.GetSize();for ( int i=0; i<nLines; i++ ){str = str + pDoc->m_strContent.GetAt( i );str = str + "\r\n"; // 换行}m_ctrlEdit->SetTabStops( 16 ); // 设置Tab符大小m_ctrlEdit->SetWindowText( str ); // 将文档内容传给控件}4,现在运行一下,文本编辑器就做好了。

C++MFC教程

C++MFC教程

第1章Visual C++基础本章首先介绍了Visual C++ 6.0的安装,然后讨论了应用程序向导、类向导,以及文档视图结构、IDE、辅助工具等几方面的内容。

应用程序向导和类向导实际上是IDE的一部分,由于特别重要,故单独列出。

辅助工具讲的是第三方开发的辅助工具,它是集成开发环境的补充,有了它,编写程序将更加轻松快捷。

本章还将针对各个难点提供多个简单而实用的例子,可以帮助读者快速学习并掌握Visual C++开发基础。

1.1.1 Visual C++ 6.0的安装1.1.2 应用程序向导1.1.3 类向导1.1.4 文档视图结构1.1.5 IDE1.1.6 辅助工具1.2.1 新建工作空间1.2.2 增加消息映射项1.2.3 关联成员变量1.2.4 调试技巧1.2.5 单文档多视图1.2.6 多文档示例1.3.1VC项目文件说明1.3.2IDE使用技巧1.3.3常见问题1.1.2 应用程序向导使用应用程序向导可以快速生成程序框架。

选择菜单“File→New”命令,此时会弹出“New”对话框,下面对该对话框中的常用选项进行逐一说明。

1.文件(Files)属性页单击“Files”标签,打开“Files”属性页,如图1-3所示。

图1-3 文件属性页文件类型虽然多,但常用的只有两种:C/C++ Header File(C/C++头文件)和C/C++ Source File (C/C++源文件)。

新建一个文件,可以按照以下步骤操作。

(1)选择合适的文件类型。

(2)如果想把新文件加入到工程内,选中“Add to project”复选框,并在下面的组合框中选择合适的工程。

如果当前没有打开任何工程,“Add to project”会被禁用。

(3)在“File”编辑框中输入合适的文件名。

(4)在“Location”编辑框中输入文件存放位置。

2.工程(Projects)属性页单击“Projects”标签,弹出“Projects”属性页,如图1-4所示。

MFC多文档多视图编程

MFC多文档多视图编程

深入了解MFC中的文挡/视结构李泽宇金刚熊联欢姜军(华中理工大学图象识别与人工智能研究所)Visual C++ 5.0 以其功能强大、用户界面友好而倍受程序员们的青睐。

但是,在当前的Microsoft 基本类库4.2 版本中,大约有将近200 个类,数千个函数,加之Microsoft 公司隐藏了一些技术细节,使得人们深入学习MFC变得十分困难。

MFC的AppWizard可以生成三种类型的应用程序:基于对话框的应用、单文档应用(SDI)和多文档应用(MDI)。

前两者的结构较简单,本文不再赘叙。

笔者拟从MFC中的文档/视结构入手,分析一些函数的流程,并解决编制MDI 应用程序过程中的一些常见问题。

(一)、了解文档/视结构MFC应用程序模型历经多年以有了相当大的发展。

有一个时期,它只是个使用应用程序对象和主窗口对象的简单模型。

在这个模型中,应用程序的数据作为成员变量保持在框架窗口类中,在框架窗口的客户区中,该数据被提交显示器。

随着MFC2。

0的问世,一种应用程序结构的新方式----MFC文档/视结构出现了。

在这种结构中,CFrameWnd繁重的任务被委派给几个不同类,实现了数据存储和显示的分离。

一般情况下,采用文档/视结构的应用程序至少应由以下对象组成:。

应用程序是一个CwinApp派生对象,它充当全部应用程序的容器。

应用程序沿消息映射网络分配消息给它的所有子程序。

框架窗口是一CfrmeWnd派生对象。

文档是一个CDocument派生对象,它存储应用程序的数据,并把这些信息提供给应用程序的其余部分。

视窗是Cview派生对象,它与其父框架窗口用户区对齐。

视窗接受用户对应用程序的输入并显示相关联的文档数据。

通常,应用程序数据存在于简单模型中的框架窗口中。

在文档/视方式中,该数据移入称为document 的独立数据对象。

当然,文档不一定是文字,文档是可以表现应用程序使用的数据集的抽象术语。

而用户输入处理及图形输出功能从框架窗口转向视图。

如何在MFC单文档中创建多视图

如何在MFC单文档中创建多视图

u 一个文档可以有多个视图,由Document中成员变量CPtrList m_ViewList维护。
u CFrameWnd拥有一个成员变量CView* m_pActiveView指向当前活动的View。
u CView中拥有一个成员变量CDocument* m_pDocument指向该视图相关的Document。
!m_wndSplitter2.CreateView(1, 0, RUNTIME_CLASS(BottomLView), CSize(350, 240), pContext) ||
!m_wndSplitter2.CreateView(0, 1, RUNTIME_CLASS(TopRView), CSize(350, 240), pContext) ||
/wang_qingyuan/blog/item/60870400275c5b087bec2cbd.html
深入分析MFC文档视图结构
2008-10-16 19:40
文档视图结构(Document/View Architecture)是MFC的精髓,也是Observer模式的具体实现框架之一,Document/View Architecture通过将数据和其表示分开,提供了很好的数据层次和表现层次的解耦。然而,虽然我们使用MFC AppWizard就可以很轻松地获得一个支持Document/View Architecture的MFC程序框架,Document/View Architecture本身的复杂性加上VC产生的一系列代码足够让我们眼花缭乱,一时陷入云里雾里不可自拔。加上我们更多的人都没有经过Windows SDK Programming 的学习和经历就直接进行MFC Programming的学习和开发,更是面对一堆的代码不知所措。

MFC的窗口分割实例以及CSplitterWnd类

MFC的窗口分割实例以及CSplitterWnd类
在 MFC 的框架下,文档对象(CDocument)有一个保存其所有视图的列表,并提供了 增加视图(AddView)与删除视图(RemoveView)函数,以及当文档内容改变时通知其所 有视图的方法(UpdateAllViews)。通过多文档框架的窗口复制机制和单文档框架的分割窗 口机制是实现单文档多视图的主要方法。
3 分割窗口ቤተ መጻሕፍቲ ባይዱ
如图 1,把窗口分成三个视图,左视图基于 CView 类,可用来作几何图形;右上视图基 于 CEditView 类,用于显示文本消息;右下视图基于 CFormView 类,在此视图中做一个文 本框及发送、清除按钮,发送按钮用来向右上视图传送消息。
图 1 设计样式 打开 Microsoft VC++ 6.0,通过 MFC AppWizard(exe)新建名为 SplitWnd 的单文档(SDI) 工程,新建工程时所有选项均按默认设定。 工程建好后,把工程中的 CSplitWndView 视图类作为左视图所对应的类(该类的实现 与本文重点无关,故不阐述,有兴趣读者可与作者联系),由于需要三个视图窗口对应三个
视图类,因此需要手动创建右上视图、右下视图对应的类,可以通过 MFC 向导向应用程序 添加两个 MFC 类(菜单“Insert | New Class>”),因为在右上视图用于显示文本,故其基类选 CEditView,类名为 CLeftTopView;另一个 MFC 类的基类选 CFormView 类,取类名为 CLeftBttmView,该类即对应右下视图(由于该类基于 CFormView 类,需要有对话框与之对 应,故应先在资源中新建对话框,对话框中的控件如图 1)。
void CLeftBttmView::OnSendMsg() { UpdateData();//更新控件变量数据,文本框对应的变量为 m_sText //通过 CMainFrame 类中的 m_wndSplitterRight 变量获得右上视图类指针 CMainFrame * pMainFrm = (CMainFrame *)AfxGetApp()->GetMainWnd(); CWnd * pWnd = pMainFrm->m_wndSplitterRight.GetPane(0, 0); CLeftTopView* pLeftTopView = DYNAMIC_DOWNCAST(CLeftTopView, pWnd); pLeftTopView ->GetMsg( m_sText + "\r\n" );//CLeftTopView 成员函数,接收数据 } 右上视图类 CLeftTopView 的成员函数 GetMsg 则需保存接收到的消息并显示,主要代 码如下: void CLeftTopView::GetMsg(CString sMsg) { m_sAllMsg += sMsg; // m_sAllMsg 为成员变量,记录所有消息 int nTextLen = GetWindowTextLength(); GetEditCtrl().SetSel(nTextLen, nTextLen); GetEditCtrl().ReplaceSel( sMsg );//显示新消息 } 有了上面两个函数就可以实现右上视图类 CLeftTopView 与右上视图类 CLeftBttmView 之间的简单通讯,类似地,可以实现所有视图之间任意的数据传递。

计算机图形学 使用VC开发绘图程序的基本方法

计算机图形学  使用VC开发绘图程序的基本方法

七、思考题(尽量做,计入成绩) :
1、为什么要用 CDC 定义一个对象来作图? Windows 使用与设备无关的图形设备环境进行显示 。MFC 基础类库定义了设备环境对象类----CDC 类。 因为使用的是 mfc,如果是 sdk 的话就得用 dc,这个 cdc 想当是一个给设备画画的笔。 2、如果要绘制多条直线,应该如何编程?
4、 VC 中编程环境中,工程(project)是什么意义?为什么要用 project 的方式管理代码?
Project 文件的扩展名是 dsp,这个文件中存放的是一个特定的工程,也就是特定的应用程序的有关信息, 每个工程都对应有一个 dsp 类型的文件。 clw 为扩展名的文件是用来存放应用程序中用到的类和资源的信 以 息的,这些信息是 VC 中的 ClassWizard 工具管理和使用类的信息来源。 因为用 project 的方式管理代码比较方便,可以看成是在一个文件夹下进行的。
3、 在 MyView.cpp 文件的 OnDraw 函数中加入如下代码。 pDC->MoveTo(100,100); pDC->LineTo(200,200); CPen *pOldPen; CPen dashPen; dashPen.CreatePen(PS_DASH,1,RGB(255,0,0)); pOldPen = pDC->SelectObject(&dashPen); pDC->LineTo(300,100); pDC->SelectObject(pOldPen); pDC->LineTo(400,200);
实验(No. 1
)题目:使用 VC 开发绘图程序的基本方法
实验目的及要求:
一、实验目的:
编写一个具有一定功能的 MFC 类库应用程序 (引入简单的视图/文档概念) 掌握 GDI 画图的基本方法, , 并调用系统函数画直线。

单文档与多文档

单文档与多文档

这一点与Windows消息 这一点与Windows消息 Windows 和控件通知消息不同, 和控件通知消息不同, 因为Windows Windows消息和控 因为Windows消息和控 件通知消息就只能被 窗口和视图处理. 窗口和视图处理.
文档/视图结构的工作机制 文档 视图结构的工作机制
视图通过GetDocument 视图通过GetDocument 成员函数获得指向相关 联的文档对象的指针 通过该指针调用文 档类的成员函数来 从文档中读取数据
16.3 CDocument类的派生类构造 类的派生类构造
构造CDocument类的派生类的基本步骤 类的派生类的基本步骤 构造 一般来说, 一般来说,从CDocument类派生自己的文档类所需的典型步骤为 类派生自己的文档类所需的典型步骤为 为每一个文档类型从CDocument类(当然也可以是其它 类 当然也可以是其它 为每一个文档类型从 CDocument类的派生类 派生一个相应的文档类. 类的派生类)派生一个相应的文档类 类的派生类 派生一个相应的文档类. 为文档类添加成员变量.这些成员变量用来保存文档的 为文档类添加成员变量. 数据,其它对象 如与文档相关联的视图 如与文档相关联的视图)直接或间接地访 数据,其它对象(如与文档相关联的视图 直接或间接地访 问这些成员变量来读取或更新文档的数据. 问这些成员变量来读取或更新文档的数据. 重载Serialize成员函数,实现文档数据的串行化. 成员函数,实现文档数据的串行化. 重载 成员函数
视图结构中 在文档/视图结构中 文档 视图
在文档和用户之 间起中介作用 除WM_COMMAND外,文档不 WM_COMMAND外 文档不 处理其它的Windows Windows消息 能处理其它的Windows消息 视图可以直接或间接 地访问文档类中的成 员变量, 员变量,它从文档类 中(而不是从存储介质 而不是从存储介质 中)将文档中的数据取 将文档中的数据取 出来, 出来,然后在屏幕上 显示文档的数据

Visual C++中Tab View的多种实现方法

Visual C++中Tab View的多种实现方法
rect.bottom - rect.top, SWP_NOZORDER);
//调整要显示的视窗口位置,使其占据标签控件的显示区
AdjustRect(FALSE, &rect);
wnd->SetWindowPos(NULL, rect.left, rect.top, rect.right - rect.left,
图1 CTabCtrl实现的Tab View
1.实现的主要类
//要切换显示的视窗口类
class CMyView1 : public CListView
class CMyView2 : public CView
//派生的标签控件类
class CViewTabCtrl : public CTabCtrl
char szLabel[32]; //标签窗口对应该视图的字符串
}TCB_ITEM;
//将每次如入的视图信息保存到列表中
CList <TCB_ITEM *,TCB_ITEM *> m_Views;
在切换时,通过函数SetWindowPos()中设置参数SWP_SHOWWINDOW或SWP_HIDEWINDOW来显示选中的新视图,或隐藏旧视图。采用这种方法,使对视图操作更加灵活,可以很方便在Tab View中添加和删除不同视图。
rect.bottom - rect.top, SWP_NOZORDER);
}
3.多个视之间切换的实现
对于图1 所示的一个SDI的程序,视的切换主要完成下面的工作:
// 步骤1:设置当前活动的子窗口的ID
CView* pOldActiveView = GetActiveView();

如何在MFC单文档中创建多视图

如何在MFC单文档中创建多视图

如何在MFC单文档中创建多视图如何在MFC单文档中创建多视图基本步骤如下:1.首先创建一个MFC单文档应用程序。

2.添加4个MFC类TopLView、BottomLView、T opRView、BottomRView,基类为CView。

3.添加一个MFC类CControlForm,基类为CFormView,对话框ID默认。

4.创建一个切分类,如MySplitter,基类为CSplitterWnd(默认基类选项中无此类,自己添加即可)。

5.在框架类Cmainframe的头文件中,添加2个MySplitter的变量(因为下面要进行两次切分操作)。

6.重写框架类Cmainframe的OnCreateClient函数,如下://第一次静态切分CreateStatic,一行两列if (!m_wndSplitter.CreateStatic(this,1,2))return FALSE;//第二次静态切分(将第一次切分后的第二列再分为2*2)及所有的子视图创建(CreateView函数)。

if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CControlForm), CSize(100, 100), pContext) || !m_wndSplitter2.CreateStatic(&m_wndSplitter,2,2,WS_CHILD |WS_VISIBLE,m_wndSplitter.IdFromRowCol(0,1))|| !m_wndSplitter2.CreateView(0, 0, RUNTIME_CLASS(TopLView), CSize(350, 240), pContext) || !m_wndSplitter2.CreateView(1, 0, RUNTIME_CLASS(BottomLView), CSize(350, 240), pContext) || !m_wndSplitter2.CreateView(0, 1, RUNTIME_CLASS(TopRView), CSize(350, 240), pContext) || !m_wndSplitter2.CreateView(1, 1,RUNTIME_CLASS(BottomRView), CSize(350, 240), pContext)) {m_wndSplitter.DestroyWindow();return FALSE;}// return CFrameWnd::OnCreateClient(lpcs, pContext); //注释掉原有的响应函数注意:记得在Mainfrm.h中添加以上五个视图类的头文件:#include "CControlForm.h"#include "T opLView.h"#include "T opRView.h"#include "BottomLView.h"#include "BottomRView.h"6. 切分视图完成,结果如下:其中,最左的视图为FormView类型,操作类似对话框(可以在Resource-Dialog看到其对应的对话框资源);右边四个的操作则类似普通视图。

MFC中实现多文档

MFC中实现多文档

MFC中实现多文档MFC(Microsoft Foundation Class)是用于Microsoft Windows操作系统的应用程序框架。

多文档是指在一个应用程序中同时打开和管理多个文档的能力。

下面是如何在MFC中实现多文档的步骤:1.创建一个新的MFC应用程序项目:- 在Visual Studio中选择“文件”>“新建”>“项目”。

- 在“左侧导航栏”中选择“Visual C++”>“MFC”。

-选择“MFC应用程序”并点击“下一步”。

-输入项目名称,并选择存储位置,然后点击“下一步”。

-选择“多文档”应用程序类型,并确保“使用多文档视图”选中,然后点击“完成”。

2.修改文档类:- 打开“xxxDoc.h”文件(xxx为你的应用程序名称)。

-在文档类声明中添加一个成员变量来保存文档的数据。

3.修改视图类:- 打开“xxxView.h”文件。

-在视图类声明中添加用户界面控件(如按钮、菜单等)来实现文档的交互操作。

-在视图类声明中,添加成员变量来保存文档数据的指针。

- 在视图类的实现文件中,重写OnInitialUpdate(函数,初始化视图。

4.修改主框架窗口类:- 打开“MainFrm.h”文件。

-在主框架窗口类声明中,添加成员变量来保存文档视图的指针。

- 在主框架窗口类的实现文件中,重写OnCreateClient(函数,创建并管理多个文档视图的布局。

5.添加命令处理函数:- 打开“xxxView.cpp”文件。

-在视图类的实现文件中,添加命令处理函数,例如保存文档、打开新文档等。

6.调试和测试:-编译并运行应用程序。

-打开多个文档,观察每个文档的窗口布局和视图。

-测试各种文档操作,如保存、打开、关闭等。

以上是使用MFC框架实现多文档的基本步骤。

根据你的具体需求,你可以进一步定制和扩展多文档功能,例如添加更多自定义的菜单和工具栏选项、实现文档之间的数据交互等。

VC++讲义第16单元 多文档视图结构

VC++讲义第16单元  多文档视图结构

第16单元多文档界面程序本单元教学目标介绍多文档界面(MDI)程序的构造和编程方法。

学习要求理解多文档界面(MDI)程序的构造,掌握其编程方法。

授课内容和框架窗口界面程序、单文档界面(SDI)程序和基于对话框的应用程序一样,多文档界面(MDI)程序也是基本的MFC应用程序结构。

MDI程序的结构最复杂,功能也最强。

其特点是用户一次可以打开多个文档,每个文档均对应不同的窗口;主窗口的菜单会自动随着当前活动的子窗口的变化而变化;可以对子窗口进行层叠、平铺等各种操作;子窗口可以在MDI主窗口区域内定位、改变大小、最大化和最小化,当最大化子窗口时,它将占满MDI主窗口的全部客户区。

MDI不仅可以在同一时间内同时打开多个文档,还可以为同一文档打开多个视图。

16.1MDI应用程序从程序员角度看,每个MDI应用程序必须有一个CMDIFrameWnd或其派生类的对象,该窗口称作MDI框架窗口。

CMDIFrameWnd是CFrameWnd的派生类,除了拥有CFrameWnd 类的全部特性外,还具有以下与MDI相关的特性:1.与SDI不同,MDI的框架窗口并不直接与一个文档和视图相关联。

MDI的框架窗口拥有客户窗口,在显示或隐藏控制条(包括工具条、状态栏、对话条)时,重新定位该子窗口。

2.MDI客户窗口是MDI子窗口的直接父窗口,它负责管理主框架窗口的客户区以及创建子窗口。

每个MDI主框架窗口都有且只有一个MDI客户窗口。

3.MDI子窗口是CMDIChildWnd或其派生类对象,CMDIChildWnd也是CFrameWnd 的派生类,用于容纳视图和文档,相当于SDI下的主框架窗口。

每打开一个文档,框架就自动为文档创建一个MDI子窗口。

一个MDI应用程序负责动态的创建和删除MDI子窗口。

在任何时刻,最多只有一个子窗口是活动的(窗口标题栏颜色呈高亮显示)。

MDI框架窗口始终与当前活动子窗口相关联,命令消息在传给MDI框架窗口之前首先分派给当前活动子窗口。

第11章单文档与多文档

第11章单文档与多文档

中(而不是从存储介质 这一点与Windows消息
中)将文档中的数据取 和控件通知消息不同,
出来,然后在屏幕上 因为Windows消息和控
显示文档的数据
件通知消息就只4能被 窗口和视图处理。
文档/视图结构的工作机制
视图通过GetDocument 成员函数获得指向相关 联的文档对象的指针
通过该指针调用文 档类的成员函数来 从文档中读取数据
无论是保存文档或是打开文档,应用程序都是通过 调用文档类的Serialize串行化成员函数来完成操作的。 因此,在大多数情况下,我们都需要重载Serialize成员 函数。Serialize成员函数带有一个CArchive类型的参数, 这是一个与所打开的文件相关联的对象。一般情况下, 总是使用CArchive对象来保存和打开文档。
由于每一个文档可以有多个视图,但 每个视图只能对应于一个确定的文档
多文档程序需要解决的问题仅仅是多 个文档的数据管理方法的问题
多文档程序,最初的文档模板只支持主窗口,但每次打开一 个新文档时都调用CDocument的函数OnNewDocument,建 立一个由CMDIChildWnd派生的新的MDI子窗口,这些窗口 中保存着各种已打开的文档,所有的细节都由MFC库处理 3
建的。
每一种文档类型都有一种文档模板与之相对应,文档模
板负责创建和管理该文档类型的所有文档。
文档模板的构造函数的原型如下:
CDocTemplate
(UINT nIDResource, //与文档一同使用的各种资源的资源标识符 CRuntimeClass* pDocClass,// 指向文档派生文档类的对象的指针 CRuntimeClass* pFrameClass, //框架类的派生框架类的对象指针 CRuntimeClass* pViewClass //指向CView的派生视图类的对象指针

VC++中MFC生成单文档程序详细过程

VC++中MFC生成单文档程序详细过程

实验内容:
� � � 按前面所学的编码规范进行程序编写 将前面基于控制台的应用程序改为基本桌面的应用程序 可采用基于对话框的应用程序也可采用基于单文档的应用程序
图书管理系统参考界面
- 11 -
一. 快速建立 MFC 应用:
在VC6.0 的集成开发环境的“File”菜单下有“New”命令,用来建立各种新的内容。 选择“File”菜单下的“New”命令,弹出“New”对话框,如图1-1 所示。
-1-
哈尔滨工业大学软件学院
程序设计实践
图 1-1 项目建立窗口
1.选择应用程序界面的类型
在“MFC AppWizard – Step 1”对话框中,主要是选择应用程序界面的类型和应用程序 资源的语言种类,如图1-2 所示。
2.程序编辑管理界面
图 1-3 应用程序编辑窗口 程序说明,在MFC 应用程序的文档/视图结构 � CHelloApp:应用程序类 � CMainFrame:主框架窗口类 � CHelloDoc:文档类,文档类用来完成应用程序数据的存取工作。 � CHelloView:视图类, 视图类完成显示数据和与使用者交互的工作。s � CAboutDlg:版本信息对话框类 。 InitInstance()函数最后的工作就是显示和更新应用程序的窗口。 如果InitInstance() 函数中所有的初始化工作均正确地进行,函数将返回TRUE。在执行完初始化工作后,应用程 序将进入消息循环,接收和处理系统发送来的各种消息,直到应用程序被关闭。 ※ 详细信息请参考“VC++简明教程.PDF”文件中第29-39页。 下面是自动生成的程序运行界面。
如图 3-1 程序运行界面 2.获取编辑框中输入的内容 有两种方式获取文本,一种是通过定义变量的方式,另一种是直接使用命令。下面简单 说一下直接使用命令的方式。

在View类中创建分割多视

在View类中创建分割多视

本文在介绍了几种标准的单文档与多视结构的VC5.0 MFC实现方法之后,介绍了笔者摸索出的另外两种实用方法,并给出了实现它们的的主要程序框架。

一、单文档与多视Windows程序一般分为以下几种风格:多文档、单文档、基于对话框的。

Word一类多文档程序和计算器一类基于对话框的程序不在本文介绍之列。

单文档又分为单视的和多视的。

一般情况下,单文档仅需要单视就够了,如画笔等。

但也有一些情况下,单文档需要多视支持,比如同时观察文档的不同部分,同时从不同的角度观察同一文档等。

在MFC的框架下,文档对象(CDocument)维持了一个保存其所有视的列表,并提供了增加与删除视的函数,以及当文档内容改变时通知其所有视的方法。

通过多文档框架的窗口复制机制和单文档框架的分割窗口机制是实现单文档多视的主要方法。

但这些标准方法在有的情况下并不够用,为此笔者摸索出另外两种实用的方法,在实践中使用效果良好。

二、三种标准的单文档与多视情况1.视对象基于同一视类,每个视位于MDI的一个独立子文档框架中。

用户可以通过“窗口\新窗口”菜单,为同一文档的视再创建一个窗口,通过新创建的窗口,可以编辑和观察文档的另一部分,同一文档各个视图之间自动实现同步,用户修改一个视的内容,在另外的视中也自动更新。

MFC框架通过复制原来的子框架窗口和其中的视来实现上面的功能,并且是完全自动的。

2.视对象基于同一视类,所有视位于同一文档框架中。

分割窗口将单文档窗口的视区分割成几个独立的视,框架从同一视类创建多个视对象。

Word的子窗口即属于这种类型。

3.视对象基于不同的视类,所有的视位于同一文档框架中。

多个视共享同一文档框架,但从不同的视类创建,每个视可以为文档提供不同的观察和编辑方法。

比如一个视用图形观察文档,而另一个视用文本编辑文档中对象的属性。

这种情况也适应于用不同的视来观察文档的不同部分。

这种类型的实现方法是通过重载OnCreateClient函数实现。

mfc ceditview实例

mfc ceditview实例

mfc ceditview实例全文共四篇示例,供读者参考第一篇示例:MFC CEditView(多文本编辑框视图)是Microsoft Foundation Class(MFC)库中的一个类,用于在应用程序中显示和编辑文本。

它提供了一个易于使用和定制的界面,使用户能够轻松地输入、编辑和查看文本信息。

在本文中,我们将介绍如何使用MFC CEditView类创建一个简单的文本编辑器实例。

我们需要创建一个新的MFC应用程序项目。

在Visual Studio 中,选择“文件” -> “新建” -> “项目”,然后选择“MFC 应用程序”模板。

在向导中,选择“单文档应用程序”类型,并确保勾选“生成视图”和“支持MFC 功能”选项。

点击完成按钮后,Visual Studio 将自动生成一个基本的MFC应用程序框架。

```cppclass CMyEditView : public CEditView{protected:CMyEditView(); // 隐藏的构造函数DECLARE_DYNCREATE(CMyEditView)``````cppIMPLEMENT_DYNCREATE(CMyEditView, CEditView)CMyEditView::CMyEditView(){}if (!m_wndSplitter.CreateView(0, 0,RUNTIME_CLASS(CMyEditView), CSize(0, 0), pContext) ||!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CListView), CSize(0, 0), pContext)){m_wndSplitter.DestroyWindow();return FALSE;}SetActiveView((CView*)m_wndSplitter.GetPane(0, 0));return TRUE;}通过上述代码,我们创建了一个名为CMyEditView的自定义CEditView类,并将其添加到应用程序的主视图中。

单文档实现多视图

单文档实现多视图
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的实现:
{
// 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));
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));

VC++文档程序应用图标的简易改变

VC++文档程序应用图标的简易改变

VC++文档程序应用图标的简易改变
杨小平
【期刊名称】《电脑开发与应用》
【年(卷),期】2001(014)011
【摘要】@@ 在使用MFC AppWizard创建应用程序时,很多是基于文档--视图结构的应用,这样创建的文档应用程序的应用图标是MFC默认的图标(MFC方块),也即是在文档应用窗口标题栏的左边的图标是MFC默认的图标(MFC方块).对于自己开发的应用程序,当然希望拥有属于自己的图标,如何改变默认图标成为自己设计的图标呢?这里以单文档为例,介绍两种无需编写程序的简单易行的方法.
【总页数】1页(P12)
【作者】杨小平
【作者单位】江西财经大学
【正文语种】中文
【中图分类】TP311.1
【相关文献】
1.VC++应用程序中多个单文档的调用 [J], 颜建洲
2.VC++环境下的多文档多窗口应用程序开发 [J], 郑相锋;王庆;冯砚厅;李中伟;李文彬
3.利用VC++改变文档窗口的实现 [J], 鹏程
4.VC++编程改变文档窗口背景 [J], 穆旭成;王建
5.怎样用VC++开发多文档多窗体应用程序 [J], 杨琦
因版权原因,仅展示原文概要,查看原文内容请购买。

用VC6.0单文档进行数字图像处理

用VC6.0单文档进行数字图像处理

用VC6.0单文档进行数字图像处理以前写一些VC6.0的数字图像处理程序,大多是用对话框写的。

主要是因为对话框就那么两个类:App类和Dlg类,所以理解也比较简单。

但是,最近,听到有人这么讲文档视图类才是MFC的核心。

所以,也想尝试一下。

这两天做了点简单的尝试,特此总结一下。

1、写一个DIB类,因为在单文档或多文档下,如果不写一个DIB 类,那么你做处理就比较麻烦了。

因为我们经常要将这个DIB类的对象来共享,比如一般的DIB类的对象都是放到Doc类中。

那么我们经常要在View类和MainFrame类中引用到Doc类的Dib类的实例。

如果是多个Doc类和View类,这种数据的共享就显得更加重要了。

2、在DIB类中要有一个获得图像像素数据的指针的函数和一个能够设置DIB类的像素数据的指针。

因为,在MainFrame类中我们需要获得Doc类的一个DIB类的对象之后,可以获得指向该对象的像素数据的指针,因为我们要对其中的像素数据进行操作。

另外,我们要将操作之后的像素数据拷贝进DIB类的对象的像素数据中。

3、DIB类中还需要有获得操作像素数据中要用到的函数:获得图像高度、获得图像宽度、获得图像位数、获得图像每行像素所占的字节数。

4、DIB类中当然还需要有读入和写出图像的函数。

5、由于菜单的响应函数都是在MainFrame类中,所以,我们需要在MainFrame类中获得Doc类和View类的指针。

获得Doc类的指针主要是利用其中的DIB类的对象;获得View类的指针主要是更新显示处理后的图像效果。

所以在MainFrame类的cpp文件的包含文件中要包含Doc类和View类的h文件。

获得方法是调用MainFrame类的GetActiveDoc()和GetActiveView()函数。

好了,下面说说主要的程序:DIB类的头文件:// Dib.h: interface for the CDib class.////////////////////////////////////////////////////////////// //////////#if !defined(AFX_DIB_H__1065C5DA_1C47_464F_A225_A AF8D2F15064__INCLUDED_)#defineAFX_DIB_H__1065C5DA_1C47_464F_A225_AAF8D2F15064__I NCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000class CDib{public:CDib();//构造函数virtual ~CDib();//析构函数private:BITMAPFILEHEADER *m_pBmfh;//保存位图文件头BYTE *m_pBmInfo;//保存位图信息头+调色板(用于显示位图)BYTE *m_pPixel;//保存位图像素数据BITMAPINFOHEADER *m_pBmih;//保存位图信息头public:BOOL m_bRead;//标志是否调用了Read函数public:int Read(CString filename);//读入位图void Draw(CDC *pDC);//显示位图int Write(CString filename);//写出位图public:DWORD GetWidth() const;//获得位图宽度DWORD GetHeight() const;//获得位图高度WORD GetBitCount() const;//获得位图位数DWORD GetLineBytes() const;//获得位图每行像素所占字节数BYTE* GetPixelPointer() const;//获得指向位图像素数据的指针void SetPixelMatrix(BYTE *newPixel);//设置位图的像素矩阵};#endif// !defined(AFX_DIB_H__1065C5DA_1C47_464F_A225_AAF8D 2F15064__INCLUDED_)DIB类的cpp文件:// Dib.cpp: implementation of the CDib class.////////////////////////////////////////////////////////////// //////////#include "stdafx.h"#include "VampireImage.h"#include "Dib.h"//包含DIB类的头文件#ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE[]=__FILE__;#define new DEBUG_NEW#endif//////////////////////////////////////////////////////////// //////////// Construction/Destruction//////////////////////////////////////////////////////////// //////////CDib::CDib(){m_pBmfh=new BITMAPFILEHEADER;m_pBmih=new BITMAPINFOHEADER;m_pBmInfo=NULL;m_pPixel=NULL;m_bRead=FALSE;}CDib::~CDib(){if(m_pBmfh){delete m_pBmfh;m_pBmfh=NULL;}if(m_pBmih){delete m_pBmih;m_pBmih=NULL;}if(m_pBmInfo){delete[] m_pBmInfo;m_pBmInfo=NULL;}if(m_pPixel){delete[] m_pPixel;m_pPixel=NULL;}}//////////////////////////////////////////////////////////////////////// Methods//////////////////////////////////////////////////////////// //////////int CDib::Read(CString filename){CFile dib;if(!dib.Open(filename,CFile::modeRead)){return -1;}if(dib.Read(m_pBmfh,sizeof(BITMAPFILEHEADER))!=size of(BITMAPFILEHEADER)){//读取位图文件头dib.Close();return -1;}m_pBmInfo=new BYTE[m_pBmfh->bfOffBits-14];//为信息头+调色板分配空间if(!m_pBmInfo){dib.Close();return -1;}if(dib.Read(m_pBmInfo,m_pBmfh->bfOffBits-14)!=(m_pBmfh->bfOffBits-14)){//读取位图信息头+调色板(如果有)delete[] m_pBmInfo;m_pBmInfo=NULL;dib.Close();return -1;}memcpy(m_pBmih,m_pBmInfo,sizeof(BITMAPINFOHEAD ER));//拷贝40字节到位图信息头中WORD bitCount=m_pBmih->biBitCount;DWORD width=m_pBmih->biWidth;DWORD height=m_pBmih->biHeight;DWORD lineBytes=(width*bitCount+31)/32*4;m_pPixel=new BYTE[height*lineBytes*sizeof(BYTE)];//为位图像素矩阵分配空间if(!m_pPixel){dib.Close();return -1;}if(dib.Read(m_pPixel,height*lineBytes*sizeof(BYTE))!=(h eight*lineBytes*sizeof(BYTE))){//读取位图像素矩阵dib.Close();delete[] m_pBmInfo;m_pBmInfo=NULL;delete[] m_pPixel;m_pPixel=NULL;return -1;}dib.Close();m_bRead=TRUE;//标志已经使用过Read函数return 0;}int CDib::Write(CString filename){CFile dib;if(!dib.Open(filename,CFile::modeWrite | CFile::modeCreate | CFile::typeBinary)){return -1;}dib.Write(m_pBmfh,sizeof(BITMAPFILEHEADER));//写入位图文件头dib.Write(m_pBmInfo,m_pBmfh->bfOffBits-14);//写入位图信息头+调色板(如果有)dib.Write(m_pPixel,GetHeight()*GetLineBytes()*sizeof(B YTE));//写入位图像素矩阵dib.Close();return 0;}void CDib::Draw(CDC *pDC){DWORD width=GetWidth();DWORD height=GetHeight();StretchDIBits(pDC->m_hDC,0,0,width,height,0,0,width,h eight,m_pPixel,(BITMAPINFO*)m_pBmInfo,DIB_RGB_COLORS ,SRCCOPY);//用StretchDIBits显示位图}//////////////////////////////////////////////////////////// //////////// Get/Set Functions//////////////////////////////////////////////////////////// //////////WORD CDib::GetBitCount() const{return m_pBmih->biBitCount;}DWORD CDib::GetWidth() const{return m_pBmih->biWidth;}DWORD CDib::GetHeight() const{return m_pBmih->biHeight;}DWORD CDib::GetLineBytes() constreturn (GetWidth()*GetBitCount()+31)/32*4;}BYTE* CDib::GetPixelPointer() const{return m_pPixel;}void CDib::SetPixelMatrix(BYTE *newPixel){delete[] m_pPixel;//删除原来的像素矩阵m_pPixel=NULL;m_pPixel=new BYTE[GetHeight()*GetLineBytes()];//为新的像素矩阵分配空间if(!m_pPixel){return;}memcpy(m_pPixel,newPixel,GetHeight()*GetLineBytes()); //将心的像素矩阵拷贝到DIB类中}View类中的OnDraw函数:void CVampireImageView::OnDraw(CDC* pDC){CVampireImageDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for native data hereif(pDoc->GetDibInstance()->m_bRead==TRUE){//如果已经读入图片,则调用DIB类的对象的Draw函数来显示位图pDoc->GetDibInstance()->Draw(pDC);}}Doc类中的获得DIB类的对象的指针的函数:CDib* CVampireImageDoc::GetDibInstance(){return m_pDib;}Doc类中的打开和保存菜单的函数:BOOL CVampireImageDoc::OnOpenDocument(LPCTSTR lpszPathName){if (!CDocument::OnOpenDocument(lpszPathName))return FALSE;// TODO: Add your specialized creation code herem_pDib->Read(lpszPathName);return TRUE;}CDib* CVampireImageDoc::GetDibInstance(){return m_pDib;}BOOL CVampireImageDoc::OnSaveDocument(LPCTSTR lpszPathName){// TODO: Add your specialized code here and/or call the base classCFileDialog sfd(false,"*.bmp",NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"BMP Files(*.bmp)|*.bmp||");if(sfd.DoModal()!=IDOK){return FALSE;}if((m_pDib->Write(sfd.GetPathName()))==-1){AfxMessageBox("保存失败");return FALSE;}return TRUE;;}MainFrame类中灰度图菜单的响应函数:void CMainFrame::OnGrayimage(){// TODO: Add your command handler code hereCVampireImageDoc*pDoc=(CVampireImageDoc*)this->GetActiveDocument();//获得当前的Doc类的指针DWORDwidth=(pDoc->GetDibInstance())->GetWidth();//获得DIB对象的宽度DWORDheight=(pDoc->GetDibInstance())->GetHeight();//获得DIB对象的高度WORDbitCount=(pDoc->GetDibInstance())->GetBitCount();//获得DIB对象的位数DWORDlineBytes=(pDoc->GetDibInstance())->GetLineBytes();//获得DIB对象的每行所占字节数BYTE*dib=(pDoc->GetDibInstance())->GetPixelPointer();//得到DIB对象的像素数据的指针BYTE *newDib=new BYTE[height*lineBytes];//新建一块内存if(!newDib){return;}memcpy(newDib,dib,height*lineBytes);//将DIB对象的像素数据拷贝至新建的内存if(bitCount==8)//如果位图是8位{AfxMessageBox("已经是8位的灰度图了,没有必要再转换。

第9章 单文档界面和多文档界面1

第9章 单文档界面和多文档界面1

2011-12-1
2
9.1 文档对象和视图对象
文档和视图的关系
文档用于数据处理和维护, 视图则用于数 文档用于数据处理和维护,而视图则用于数 数据处理 据的显示 在文档/视图结构的应用程序编程中 显示, 视图结构的应用程序编程中, 据的显示,在文档 视图结构的应用程序编程中, 主要的工作就是用代码操作文档对象 视图对象。 操作文档对象与 主要的工作就是用代码操作文档对象与视图对象。 在关于文档对象与视图对象的代码中一般要 调用方法Cview::GetDocument(),通过 调用方法 , GetDocument()可以返回指向联系的视图对象, 可以返回指向联系的视图对象 可以返回指向联系的视图对象, 一般地,当视图为人机交互界面时, 一般地,当视图为人机交互界面时,如果用户在 视图中对文档数据进行编辑, 视图中对文档数据进行编辑,视图将接收到此消 再发送消息通知文档对象更新文档数据, 息,再发送消息通知文档对象更新文档数据,这 时可用GetDocument()得到被操作的文档对象。 得到被操作的文档对象。 时可用 得到被操作的文档对象
2011-12-1
பைடு நூலகம்
5
习题
1.MFC中文档和视图的关系是什么? . 中文档和视图的关系是什么? 中文档和视图的关系是什么 2.文档的主要作用是什么? .文档的主要作用是什么? 3.视图的主要作用是什么? .视图的主要作用是什么?
2011-12-1
6
第9章 单文档界面和多文档界面 章
内 容 提 要
1
文档对象和视图对象
2
单文档界面
3
多文档界面
2011-12-1
1
9.1 文档对象和视图对象
文档对象:文档对象用于存储程序数据, 文档对象 文档对象用于存储程序数据,在 文档对象用于存储程序数据 应用程序中,要使数据存放到文档对象中, 应用程序中,要使数据存放到文档对象中, 就应将存储的数据作为文档对象的成员变 的文档类由Cdocument类所派生。 量。MFC的文档类由 的文档类由 类所派生。 视图对象:显示文档数据以及接受用户的输 视图对象 显示文档数据以及接受用户的输 入和编辑, 入和编辑,视图对象的一个非常重要的成 函数, 员函数是OnDraw()函数,每当窗口需要重 员函数是 函数 画时就将调用此函数, 画时就将调用此函数,MFC的视图类由 的视图类由 Cview类所派生。 类所派生。 类所派生
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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);pNewActiveView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);RecalcLayout();}5)完成菜单的命令处理函数void CMainFrame::OnViewFirstView(){SwitchToView(FIRST);}void CMainFrame::OnViewSecondView(){SwitchToView(SECOND);}6)对文档类的同一数据在多视图中进行不同形式的显示。

为CFirstView和CSecondView的OnDraw函数添加显示文档类对象数据的代码。

本例中,文档类数据为一字符串变量:StrData = "The string will be displayed in first view in string format, and in second view in hex format."。

在CFirstView的视图中用字符串形式显示:void CFirstView::OnDraw(CDC* pDC){CDocument* pDoc = GetDocument();CString strDoc = ((CDemoDoc*)pDoc)->strData;pDC->TextOut(100, 100, strDoc);}在CSecondView的视图中对每个字符用十六进制的形式显示:void CSecondView::OnDraw(CDC* pDC){CDocument* pDoc = GetDocument();TEXTMETRIC tm;pDC->GetTextMetrics(&tm);CString strDoc = ((CSDMV_DemoDoc*)pDoc)->strData;int nStrLen = strDoc.GetLength();CString strTempChar;for (int i = 0; i < nStrLen; i ++) {strTempChar.Format("%02x ", strDoc.GetAt(i));pDC->TextOut(10+i*tm.tmAveCharWidth*3, 100,strTempChar);}}7)完成视图更新机制。

当文档类对象的数据发生变化后,调用Invalidate函数更新当前视图。

void DemoDoc::OnEditChangeData(){AfxGetApp()->m_pMainWnd->Invalidate(FALSE);}经过以上步骤,就可以实现单文档多视的程序框架。

参考文献1 David J. Kruglinski等 Programming Visual C++ 1999年5月2 J effrey Richter Windows高级编程指南 1999.63 Microsoft公司 MSDN Library 1998年2008年5月10日作者简介:池晓春,2003年6月毕业于海军工程大学指挥自动化专业,2003年6月至今服役于91550部队指控中心担任助理工程师。

赵鹤群,。

相关文档
最新文档