文档视结构
基于框架结构的序列化
在一个基于MFC的Windows应用程序中,无论是 保存文档还是打开文档,应用程序都是通过调用文档 类的Serialize成员函数来完成串行化操作的。因此,在 大多数情况下,我们都需要通过重载Serialize成员函数 来实现文档的串行化。Serialize成员函数带有一个 CArchive类型的参数,这是一个与所打开的文件相关 联的对象。一般情况下,我们总是使用CArchive对象 来保存和打开文档。
数据文件的读写
我们在实现的应用程序中通常需要对数据进行保存, 或是从外部存储介质上读取数据,这就涉及到文件的操作。 我们可以利用各种文件存取方法完成这些工作,但MFC中 也提供了一种读写文件的简单方法——“序列化”(即 Serialize ,该函数为虚函数)。序列化机制通过更高层次 的接口功能向开发者提供了更利于使用和透明于字节流的 文件操纵方法,举一个例子来讲你可以将一个字符串写入 文件而不需要理会具体长度,读出时也是一样。你甚至可 以对字符串数组进行操作。在MFC提供的可自动分配内存 的类的支持下你可以更轻松的读/写数据。你也可以根据 需要编写你自己的具有序列化功能的类。
第5章 文档/视结构
文档/视结构是Microsoft公司为Visual C++ Windows程 序设计提出的一种新的编程机制。它是我们在Visual C++ 中使用MFC开发基于文档的应用程序的基本框架,在这 个框架中,数据的维护和显示是分别由两个不同的且彼 此紧密相关的两个对象——文档和视负责的。在文档/视 结构中,文档相当于一个数据容器或数据管理中心,而 视却相当于显示数据的窗口或者是和数据发生交互的窗 口。因此一个完整的基于MFC开发的应用程序一般至少 由四个类组成(SDI应用):CWinApp应用类, CFrameWnd窗口框架类,CDocument文档类,CView视 类(Visual C++ V6.0中支持创建不带文档-视结构的应 用)。文档/视结构在很多场合与传统的编程方式相比要 更有利于这一类应用程序的编写。
Visual C ++ 类CSplitterWnd 简介
类CSplitterWnd 是 MFC类库中实现分割器窗口的基类,根据需要可 以从该类派生自己的分割器窗口类。分割器窗口是含有多个窗格的窗口, 每个窗格通常是应用程序特定的由 CView派生类的对象,也可以是具有 适当子窗口 ID 的任何 CWnd对象。类CSplitterWnd是类CWnd的派生类, 因此,类CSplitterWnd除了继承类CWnd方法外,还有以下方法: 构造函数: CSplitterWnd 该函数构造一个类CSplitterWnd的对象 Create 该 函 数 创 建 动 态 分 割 器 窗 口 并 将 此 窗 口 连 接 给 类 CSplitterWnd的对象 CreateStatic 该 函 数 创 建 静 态 分 割 器 窗 口 并 将 此 窗 口 连 接 给 类 CSplitterWnd的对象 CreateView 该函数在分割器窗口中创建一个窗格
一般情况下,采用文档/视结构的应用程序(如SDI应用)至 少应由以下4个对象组成: 应用程序对象:该对象是一个从 CWinApp 类派生的类的对 象,它是应用程序的中心。应用程序对象将消息沿消息映射网络分 配给它的所有子程序。 框架窗口对象:该对象是一个从 CFrameWnd 类派生的类的 对象。 文档对象:该对象是一个从 CDocument类派生的类的对象, 它主要用来存储应用程序中的数据,并把这些信息提供给应用程序 的其它部分。 视窗对象:该对象是从CView类派生的类的对象,它与其父 框架窗口用户区对齐。视窗接受用户对应用程序的输入并显示相关 联的文档数据。
实现一个类,怎样使其具有序列化功能呢?你需 要做以下的工作: 1. 2. 3. 4.
该类从CObject派生。 在类声明中包括DECLARE_SERIAL宏定义。 提供一个缺省的构造函数。 在类中实现Serialze函数
5.
使用IMPLEMENT_SERIAL指明类名和版
本号
定制序列化
定制序列化是区别上述序列化的一种实现数据存储 的序列化方法 , 定制序列化进行数据存储与框架无关即 数据文件存储与文档类无关。通常与以下类相关: l l CFile 文件类 CStdioFile 标准I/O文件类
GetScrollStyle 返回共享滚动条的风格
SetScቤተ መጻሕፍቲ ባይዱollStyle 为该分割器窗口共享的滚动条指定新的滚动
分割器视窗的实现
单文档应用程序和多文档应用程序的分割器窗口实现技 术基本相同,只是基于父框架窗口类不一样而已。单文档应 用程序嵌入一个CSplitterWnd成员变量是基于父框架窗口类 CMainFrame类,CMainFrame类是CFrameWnd的派生类;而多 文档应用程序是基于CMDIChildWnd的派生类,用AppWizard 生成的多文档应用程序嵌入一个CSplitterWnd成员变量是基于 CChildFrame类,CChildFrame类是CMDIChildWnd的派生类; 当然也可以基于用ClassWizard 生成的其他CMDIChildWnd的 派生类。
操作事件与应用程序框架
我们在Windows应用中,输入数据主要是通过鼠标、键盘和点击菜单条和 工具条来进行人机交互的。操作事件当然与这些输入数据操作有关。 鼠标操作是目前Windows 软件的主要人机互动方式。Windows软件根据鼠 标动作产生的消息作相应处理。因此,鼠标消息是我们经常要处理的消息, 其消息主要分为:鼠标移动、按钮按下、松开、双击等消息。我们可以利用 ClassWizard为这些消息添加相应的消息映射。 键盘同鼠标一样是Windows应用程序共享的全局硬件资源,键盘事件是由 消息、消息映射极其消息处理函数来处理的。Windows 发送键盘消息给具有 输入焦点的窗口,通知窗口用户正击什么键,通常这些消息有: WM_KEYDOWN 和WM_KEYUP 。除Alt外,所有键发送 WM_KEYDOWN 和 WM_KEYUP消息。利用菜单接受用户命令是一种很简单的交互方法,同时 也是一种很有效的方法。通常菜单作为一种资源存储在文件中,因此我们可 以在设计时就利用资源编辑器设计好一个菜单。关于使用Visual C++ 设计菜 单前面已述这里我就不再多讲了,但这里我要提醒大家是你在编写菜单时应 该尽量在属性对话框的底部提示(Prompt)处输入文字,这虽然不是必要的, 但MFC在有状态栏和工具条的情况下会使用该文字,文字的格式为“状态栏 显示说明\n工具条提示”。
操作函数:
GetRowCount 返回当前窗格的行计数值 GetColumnCount 返回当前窗格的列计数值 GetRowInfo SetRowInfo 返回指定行上的信息 设置指定行上的信息
GetColumnInfo 返回指定列上的信息 SetColumnInfo 设置指定列上的信息 GetPane IsChildPane 子窗口 IdFromRowCol 返回指定行列处的窗格的子窗口 ID 值 RecalcLayout 该分割器窗口 在调整行或列尺寸后,调用该函数重新显示 返回指定行列处的窗格 确定一个窗口当前是否是这个分割器窗口的
总之,在文档/视方式中,文档和视是分离的,即:文档用于保存数据, 而视是用来显示这些数据。文档模板维护它们之间的关西。这种文档/视结 构在开发大型软件项目时特别方便、有用。
在文档/视应用程序中,CWinApp派生类对象拥有并控制文档模板,文 档模板产生文档、框架窗口及视窗。从用户的角度来看,视窗实际上是一 个普通的窗口。象其他基于Widnows应用程序的窗口一样,人们可以改变 它的尺寸大小,对它进行移动,也可以随时关闭它。若从程序员的角度来 看,视窗实际上是一个从MFC类库中的CView类所派生出的类的对象。文 档对象是用来保存数据的,而视窗对象是用来显示数据的,并且允许对数 据进行编辑。SDI或MDI的文档类是由CDocument类派生出来的,它可以有 一个或多个视类,而这些视类最终都是由CView类派生出来的。视对象只 有一个与之相联系的文档对象,它所包含的CView::GetDocument函数允许 应用在视中得到与之相联系的文档,据此,应用程序可以对文档类成员函 数及公共数据成员进行访问。如果视对象接受到了一条消息,表示用户在 编辑控制中输入了新的数据,此时,视就必须通知文档对象对其内部数据 进行相应的更新。如果文档数据发生了变化,则所有的视窗都必须被通知 到,以便它们能够对所显示的数据进行相应的更新。 Document::UpdateAllViews函数即可完成此功能。
通常,应用程序数据存放于简单模型中的框架窗口中。在文档/视结 构应用中,该数据被放在称为文档的独立数据对象中。当然,文档不一 定就是文字,文档可以是表现应用程序使用的数据集的抽象术语。而用 户输入处理及图形输出功能从框架窗口转向视图。单独的视窗完全遮蔽 框架窗口的客户区,这意味着即使程序员直接绘画至框架窗口的客户区, 视图仍遮蔽绘画,在屏幕上不出现任何信息。所以输出必须通过视图。 框架窗口仅仅是个视图容器。注意:Visual C++可以建立只有视窗而没
在应用中一个视对应一个文档,但一个文档可以包含多个视。 一个应用中只用一个框架窗口,对多文档界面来讲可能有多个 MDI 子窗口。每一个视都是一个子窗口,在单文档界面中父窗 口即是框架窗口,在多文档界面中父窗口为 MDI子窗口。一个 多文档应用中可以包含多个文档模板,一个模板定义了一个文 档和一个或多个视之间的对应关系。同一个文档可以属于多个 模板,但一个模板中只允许定义一个文档。同样一个视也可以 属于多个文档模板。
应用程序对象
Doc文档模板A
Doc2文档模板B
Doc1实例
Doc2实例
Doc3实例
Doc1实例
Doc2实例
图5.2 有两种文档类型的MDI应用程序
文档、视和应用程序框架