680 likes | 846 Views
第 3 章 文档和视图. 引言. 了解 文档与视图结构程序的工作原理 掌握 应用程序中的菜单界面设计方法 掌握 工具栏和状态栏等程序界面的设计方法 了解 文档的序列化工作原理 了解 使用不同的视图类编程. 3.1 文档与视图结构. 3.1.1 文档与视图结构概述. 在文档 — 视图结构中,文档的任务是对数据进行管理和维护。数据通常被保存在文档类的成员变量中。在 Visual C++ 2005 中,文档类通过一个称为 串行化 (serialize) 的过程将数据保存到磁盘文件或数据库中。
E N D
引言 • 了解文档与视图结构程序的工作原理 • 掌握应用程序中的菜单界面设计方法 • 掌握工具栏和状态栏等程序界面的设计方法 • 了解文档的序列化工作原理 • 了解使用不同的视图类编程
3.1.1 文档与视图结构概述 • 在文档—视图结构中,文档的任务是对数据进行管理和维护。数据通常被保存在文档类的成员变量中。在Visual C++ 2005中,文档类通过一个称为串行化(serialize)的过程将数据保存到磁盘文件或数据库中。 • MFC类库为数据的串行化提供了默认的支持,只需要在此基础上稍加修改,就可以为自定义的文档类提供串行化支持。 • 在MFC中主要有两种类型的文档视图结构,即单文档界面(SDI:Single Document Interface)应用程序和多文档界面(MDI:Multiple Document Interface)应用程序。
SDI应用程序的5个基类之间的关系模型如图3.1所示。SDI应用程序的5个基类之间的关系模型如图3.1所示。 图3.1 SDI的基本类结构布局
图3.2 MDI的基本类结构布局 • MDI应用程序的6个基类之间的关系模型如图3.2所示
视图在文档和用户之间起中介作用,它只负责实现和修改文档数据,但不负责存储。 • 一个视图是一个没有边框的窗口,它位于主框架窗口区的客户区。视图是文档对外显示的窗口,但是它不能完全独立,必须依存在一个框架窗口内。 • 每一个文档可以有多个视图,但每个视图只能对应于一个确定的文档。 • 视图是文档的不同表现形式。
3.1.2 文档与视图间的相互作用 • 文档与视图的交互是通过类的共有成员变量和成员函数来实现的。表3.1给出了文档—视图结构中各类对象相互访问所采用的成员函数。 表3.1 对象访问所需函数
3.1.3 多文档应用程序 • Visual C++ 2005中的一个多文档应用程序有一个主窗口,在主窗口中可以同时打开多个子窗口,每一个子窗口对应一个不同的文档。 • 利用MFC 应用程序向导可以很方便地建立一个多文档应用程序。
1.多文档应用程序 • 【例3.1】编写一个多文档应用程序MyMdi,程序运行后在客户区窗口显示信息“这是hello world的多文档程序!”。
程序的实现过程如下: • (1)创建应用程序框架 • (2)添加代码 • 在MyMdi应用程序的CMyMdiView类的OnDraw函数中添加显示文本的代码 • pDC->TextOut(50,50, _T("欢迎学习建立多文档程序!")); • TextOut函数用于在指定的位置输出字符串。
2.文档模板 • 在文档-视图结构应用程序中,数据以文档类的对象形式存在。 • MFC提供了抽象基类CDocTemplate来实现文档模板的功能,应用程序不能直接使用,但可以把文档模板定义为CDocTemplate的派生类,在应用程序中,必须为每种类型的文档建立一个文档模板。
(1)文档模板的构成 • 文档模板定义了三个类之间的关系。 • ① 文档类 • 应用程序从CDocument类派生此类,用于完成文档的新建、打开和保存等工作。 • ② 视图类 • 应用程序从CView、CScrollView、CEditView类派生而来,用于显示文档数据。 • ③ 含有该视图文档的框架窗口类 • 单文档应用程序从CFrameWnd类派生此类,多文档应用程序从CMDIChildWnd类派生而来。如果应用程序不需要定制框架窗口,则也可以直接使用CFrameWnd类和CMDIChildWnd类。
MFC除了提供了CDocTemplate抽象基类之外,还提供了CDocTemplate的两个派生类:CSingleDocTemplate和CMultiDocTemplate。MFC除了提供了CDocTemplate抽象基类之外,还提供了CDocTemplate的两个派生类:CSingleDocTemplate和CMultiDocTemplate。 • CSingleDocTemplate类定义了一个实现单文档界面的文档模板。SDI应用程序使用主框架窗口来显示一个文档,每次只能打开一个文档。 • CMultiDocTemplate类定义了一个实现多文档界面的文档模板。MDI应用程序用主框架窗口作为工作空间,在其中可以打开单个或多个文档框架窗口。在每个文档窗口中显示一个文档。
(2)文档模板的创建 • 在初始化应用程序时,必须首先注册文档模板,以便程序利用这个模板来完成主框架窗口、视图、文档对象的创建和资源的装入。 • 在SDI或MDI应用程序中,要注册文档模板,需通过new运算符调用文档模板类的构造函数生成一个CSingleDocTemplate或CMultiDocTemplate类对象,并调用函数AddDocTemplate注册该文档模板对象。
菜单分为两类: • 一类是依附于框架窗口的一般菜单,包括主菜单和子菜单,主菜单(菜单栏)横放在窗口的顶部,它是应用程序的最高层菜单,子菜单是从主菜单下弹出的菜单。 • 另一类是弹出式菜单,也叫快捷菜单或上下文菜单,它是点击鼠标右键后,在光标所在位置出现的浮动式自由菜单。
3.2.1 建立菜单资源 • 菜单是Windows应用程序中一个必不可少的用户界面资源,Visual C++ 2005集成开发环境提供了一个可视化菜单编辑器用于菜单的编辑和添加。 • 菜单中的每一个菜单项都由菜单项名(即Caption)和命令ID号两个基本要素组成。
创建菜单可以有好几种方法,最简单的方法是在属性窗口用菜单编辑器来进行设计。创建菜单可以有好几种方法,最简单的方法是在属性窗口用菜单编辑器来进行设计。 • 利用菜单辑器创建菜单资源的主要步骤如下: • (1)打开应用程序的菜单编辑器; • (2)添加主菜单; • (3)添加菜单项,设置菜单项的属性。
【例3.2】编写一个应用程序MyMenu,为程序添加一个“图像”主菜单和它的两个下拉子菜单项“显示”和“删除”。【例3.2】编写一个应用程序MyMenu,为程序添加一个“图像”主菜单和它的两个下拉子菜单项“显示”和“删除”。 • 程序的实现过程如下: • (1)创建应用程序,打开菜单编辑器 • (2)添加主菜单 • (3)添加菜单项,设置菜单项的属性
3.2.2 添加命令处理函数 • Windows应用程序是通过消息传递机制运作的,菜单项对命令的激发、调用是通过发送WM_COMMAND消息实现的。 • 处理的原则是:依据菜单的不同作用进行不同的映射。 • 如果该菜单用于文档的显示编辑,则最好在视图类中映射。 • 如果该菜单用于文档的打开和存储,则最好在文档类中进行映射。 • 对于通用菜单,可以在框架类中映射。
在【例3.2】中只添加了菜单资源,并没有实现菜单的功能,即没有对应的命令处理函数与菜单项对应,因此,程序运行后添加的菜单项是灰色的,即处于当前不可用状态。添加新的菜单项后,还应该为新的菜单项指定一个处理函数。 • (1)打开类视图找到相应的类。 • (2)单击其属性窗口中的“事件”按钮,此时属性窗口将列出此类可以处理的对象ID。 • (3)从“菜单命令”中选择ID_SHOWPICTURE,并单击其左侧的“+”号,就会出现可处理的命令消息。 • (4)选择适当的消息,单击其右侧的单元格,就会出现提示信息
快捷键的添加需要使用快捷键编辑器,添加快捷键的步骤如下:快捷键的添加需要使用快捷键编辑器,添加快捷键的步骤如下: • (1)打开应用程序的加速器表; • (2)添加新的快捷键; • (3)设置快捷键的属性。
Visual C++ 2005的MFC提供的菜单类的对象可以用来表示各种Windows菜单,并且该类可以在程序运行时处理有关菜单的操作。 • 1. 创建菜单 • CMenu类的成员函数CreateMenu和CreatePopupMenu分别用来创建一个菜单或子菜单框架,它们的函数原型如下: • BOOL CreateMenu(); //产生一个空菜单 • BOOL CreatePopupMenu(); //产生一个空的弹出式子菜单 • 2. 装入菜单 • CMenu类的成员函数LoadMenu可用来将菜单资源装入应用程序中,它的函数原型有两种: • BOOL LoadMenu(LPCTSTR lpszResourceName); • BOOL LoadMenu(UNIT nIDResource);
3. 添加菜单项 • 当菜单创建后,可以调用CMenu类提供的成员函数AppendMenu或InsertMenu向菜单中添加一些菜单项 • 它们的函数原型如下: • BOOL AppendMenu(UNIT nFlags, UNIT nIDNewItem,const CBitmap * pBmp); • BOOL AppendMenu(UNIT nFlags, UNIT nIDNewItem=0,LPCTSTR lpszNewItem=NULL); • BOOL InsertMenu(UNIT nPosition, UNIT nFlags, UNIT nIDNewItem,const CBitmap *pBmp); • BOOL InsertMenu(UNIT nPosition, UNIT nFlags, UNIT nIDNewItem=0,LPCTSTR lpszNewItem=NULL); • BOOL InsertMenuItem(UINT uItem, LPMENUITEMINFO lpMenuItemInfo,BOOL fByPos = FALSE);
4.删除菜单项 • 当要删除指定的菜单项时,可利用CMenu类的成员函数DeleteMenu来完成,该函数的原型为: • BOOL DeleteMenu(UNIT nPosition,UNIT nFlags); • 5.获取菜单项 • 可以利用CMenu类的以下3个成员函数分别获得菜单的项数、菜单项的ID号以及弹出式子菜单的句柄。 • GetMenuItemCount()函数 • GetMenuItemID()函数 • GetSubMenu()函数
3.2.3 弹出式菜单 • 弹出式菜单是通过利用CMenu类和其成员函数,在程序运行过程中动态建立的。弹出式菜单的建立方法有两种: • (1)利用现有的菜单项进行创建。 • (2)为弹出式菜单专门建立一个菜单资源,通过调用函数CMenu::LoadMenu装入创建的菜单资源。
弹出式菜单的实现过程如下: • (1)利用成员函数CMenu::CreatePopupMenu创建一个弹出式菜单。 • (2)利用成员函数CMenu::LoadMenu装入菜单资源或利用成员函数CMenu::AppendMenu添加菜单项。 • (3)利用成员函数CMenu::TrackPopupMenu在指定位置显示弹出式菜单,并跟踪用户的菜单项选择。TrackPopupMenu成员函数的原型为: • BOOL TrackPopupMenu (UNIT nFlags, int x, int y, CWnd *pWnd, LPCRECT lpRect=0);
【例3.6】为【例3.5】的程序MyMenu的“图像”菜单添加弹出式菜单。编译运行该程序,单击鼠标右键并松开后得到如图3.12所示的结果。【例3.6】为【例3.5】的程序MyMenu的“图像”菜单添加弹出式菜单。编译运行该程序,单击鼠标右键并松开后得到如图3.12所示的结果。 图3.12 弹出式菜单
程序的实现过程如下: • (1)打开【例3.5】的例子,在Visual C++ 2005中,选择“文件”菜单中的“打开”菜单项下的“项目/解决方案”,打开上例中的“MyMenu.sln”文件。 • (2)在类视图中选择类CMyMenuView,在属性窗口单击“消息”按钮,选择WM_CONTEXTMENU,单击右侧下拉菜单中的“<添加>OnContextMenu”选项,就在视图类CMyMenuView中添加了消息WM_CONTEXTMENU的消息映射函数。
工具栏和状态栏是Windows系统中常用的两种界面元素。工具栏和状态栏是Windows系统中常用的两种界面元素。 • 一般情况下,在创建应用程序框架时,MFC自动为应用程序提供了一个标准工具栏和一个标准状态栏。
3.3.1 添加工具栏 • 工具栏是一系列工具按钮的组合,也是一种常用的命令输入方式,用户可以用鼠标单击工具栏上的工具按钮来向应用程序发出命令。 • MFC工具栏还支持工具提示(Tooltip),工具提示用于帮助用户理解单个工具栏按钮的作用。 • 工具栏也是资源,在Visual C++ 2005中创建工具栏资源 。
1.创建工具栏资源 • 创建工具栏资源的步骤如下: • (1)打开应用程序的工具栏编辑器; • (2)添加工具栏按钮; • (3)设置工具栏按钮属性。
【例3.7】为【例3.6】的程序MyMenu的“图像”菜单项添加工具栏按钮。程序运行后,工具栏的实际效果如图3.13所示,新添加的工具栏按钮位于工具栏的最后两个位置。【例3.7】为【例3.6】的程序MyMenu的“图像”菜单项添加工具栏按钮。程序运行后,工具栏的实际效果如图3.13所示,新添加的工具栏按钮位于工具栏的最后两个位置。 图3.13 MyMenu的工具栏
程序的实现过程如下: • (1)打开【例3.6】的例子,在Visual C++ 2005中,选择“文件”菜单中的“打开”菜单项下的“项目/解决方案”,打开上例中的“MyMenu.sln”文件。 • (2)在“资源视图”中展开“Toolbar”,双击其下的IDR_MAINFRAME ,打开工具栏编辑器,屏幕上同时显示工具栏设计窗口。 • (3)添加工具栏按钮。 • (4)设置工具栏按钮属性。
2.动态生成工具栏 • 动态生成工具栏的方法如下: • (1)声明一个CToolBar类对象。 • (2)调用函数CToolBar::Create或CToolBar::CreateEx生成指定风格的工具栏并与CToolBar类对象相连接。 • (3)调用函数CToolBar::LoadToolBar装入工具栏。
【例3.8】为【例3.6】的程序MyMenu动态生成工具栏,程序的实际运行效果如图3.18所示。【例3.8】为【例3.6】的程序MyMenu动态生成工具栏,程序的实际运行效果如图3.18所示。 图3.18 动态生成程序MyMenu的工具栏
程序的实现过程如下: • (1)打开【例3.6】的例子,在Visual C++ 2005中,选择“文件”菜单中的“打开”菜单项下的“项目/解决方案”,打开上例中的“MyMenu.sln”文件。 • (2)添加一个工具栏资源。 • (3)如【例3.7】的方法设置工具栏按钮的属性。 • (4)加载工具栏资源。
3.3.2 定制状态栏 • MFC提供另一种经常与输入命令相关的用户界面对象:状态栏。 • 状态栏是典型的位于应用程序主窗口底部的窗口,经常在状态栏显示文本提示信息。
MFC把状态栏封装在状态栏类CStatusBar中,动态创建状态栏的过程如下:MFC把状态栏封装在状态栏类CStatusBar中,动态创建状态栏的过程如下: • (1)构造一个CStatusBar类对象。 • (2)调用Create函数创建一个状态栏窗口,并将该窗口连接到该 CStatusBar类对象 上。 • (3)调用SetIndicators函数设置指示器ID。
利用向导创建应用程序时,在CMainFrame类中定义了一个成员变量m_wndStatusBar,它是状态栏类CStatusBar的对象。在MFC应用程序框架的实现文件MainFrm.cpp中,为状态栏定义了一个静态数组indicators,如下所示:利用向导创建应用程序时,在CMainFrame类中定义了一个成员变量m_wndStatusBar,它是状态栏类CStatusBar的对象。在MFC应用程序框架的实现文件MainFrm.cpp中,为状态栏定义了一个静态数组indicators,如下所示: static UINT indicators[] = { //定义分隔符,作为提示信息行的面板标志 ID_SEPARATOR, ID_INDICATOR_CAPS, //大写指示器面板标志 ID_INDICATOR_NUM, //数字指示器面板标志 ID_INDICATOR_SCRL, //滚动指示器面板标志 };
创建状态栏资源的具体步骤如下: • (1)打开应用程序的串表编辑器; • (2)添加新的串表,设置其属性; • (3)添加指示器面板。
【例3.9】修改【例3.7】的程序MyMenu,在状态栏上显示鼠标的位置,以及当前的状态(是显示图片还是删除图片)。程序的实际运行效果如图3.19所示。【例3.9】修改【例3.7】的程序MyMenu,在状态栏上显示鼠标的位置,以及当前的状态(是显示图片还是删除图片)。程序的实际运行效果如图3.19所示。 图3.19 MyMenu的状态栏
程序的实现过程如下: • (1)打开【例3.7】的例子,在Visual C++ 2005中,选择“文件”菜单中的“打开”菜单项下的“项目/解决方案”,打开上例中的“MyMenu.sln”文件。 • (2)添加串表。 • (3)添加指示器面板。 • (4)添加消息映射函数OnMouseMove。 • (5)修改OnDraw函数,添加显示当前状态的代码。
用户处理的数据往往需要存盘做永久备份,在MFC应用程序中提供了数据序列化(serialize)的方式来处理文档的读写功能。用户处理的数据往往需要存盘做永久备份,在MFC应用程序中提供了数据序列化(serialize)的方式来处理文档的读写功能。 • 序列化指的是从一个持久性存储介质读出或者写入一个对象的过程。
3.4.1 序列化工作原理 • 文档类存盘的重点在于存储文档类中的成员变量,使之可以利用这些变量完成重建,而不损失任何信息。 • 同时文档还需要能够从存储的文档文件中读取信息以便重建文档类。