文档/视图结构开发实例
下面在单文档应用程序框架的基础上,逐步开发一个典型的文档/视图结构的绘图程序,通过程序的具体开发,说明有关视图对象和文档对象的具体开发过程和方法。
一、实例说明
本实例在单文档应用程序框架的基础上,进行开发,最终实现一个简单的屏幕绘图程序。首先从最基本的视图绘图处理开始,逐渐加入文档的处理、数据的序列化、实现滚动窗口等功能。
二、视图的处理
要在屏幕进行绘图操作,必须在视图类中实现。即读取用户的鼠标输入以及绘图操作都必须在视图类中完成。本节将结合实例,讲解与视图类实现有关的资源及编程方法。
绘图操作的实现过程为:当用户在窗口客户区按下鼠标左键,并移动鼠标时,用连线的方式绘制鼠标经过的点,即所绘制的图形为鼠标的移动轨迹。而当用户释放左键时,停止绘图。实现过程如下。
1在视图类中定义成员变量
在CSDocDemoView.h中添加成员变量:
在CSDocDemoView.cpp中构造函数中初始化成员变量:
全局函数AfxGetApp( ) 回指向应用程序对象的一个指针,通过该指针调用CWinApp类成员函数LoadStandardCursor( )载入系统定义的光标资源。
2 添加鼠标消息映射及消息处理函数
OnLButtonDown( );
OnLButtonUp( );
OnMouseMove( );
例:
2.1 消息处理函数声明
2.2添加消息映射
2.3完善消息处理函数
3添加鼠标消息处理函数代码,实现绘图操作
在CSDocDemoView 类的资源文件中,添加鼠标消息处理函数实现代码,如下:
4设置视图窗口的特性 (非必需)
在视图类的PreCreatWindow函数中,可以实现视图窗口的特性。CSDocDemoView类已经自动重载了该函数,在其中添加代码实现视图的光标为箭头光标,窗口背景为浅灰色,代码如下:
(自生成时,本虚函数已存在,只等重载。)
5 修改程序窗口标题栏
打开String Table资源,选择ID为IDR_MAINFRAME的字符串,双击它,修改之。
6 编译运行
按F5编译程序,即可以利用鼠标在客户窗口中进行绘图操作,如下图示。
可见,仅在视图类中就可以实现客户窗口的绘图操作。然而这种绘图是很不稳定的,当窗口大小改变或覆盖(ugl)引起重绘时,所绘图形就会消失。而解决这个问题,可以将图形信息保存在文档对象中,当窗口重绘时,根据这些保存的信息重新绘制。
三、文档的处理
本节将在上节的程序的基础上,在文档类中通过一个数组保存视图窗口所绘制的线条坐标,当窗口重绘时,能够再现已绘图形。另外,还给程序添加了一个“撤销”菜单命令项,能够撤销前一步的绘图操作。下面详细介绍实现过程。
1. 创建类CLineDraw存放线条
在工程中,添加一个派生自CObject类的新类CLineDraw,用于实现与图形线条有关的操作。头文件“LineDraw.h”的实现如下:
实现文件内容如下:
2 在文档类CSDocDemoDoc中,实现存储线条坐标
在文档类CSDocDemoDoc的头文件中定义数组对象和操作CLineDraw对象的相关函数。如下:
在文档类CSDocDemoDoc的实现文件中定义函数,如下:
3 在视图中,绘制直线的同时,将直线保存到数组中
由前面介绍,绘制直线的操作是在OnMouseMove()函数中实现的,这里将OnMouseMove( )代码修改如下:
4 重写视图类中的OnDraw( )函数
当视图窗口进重绘时,它会调用视图类中的OnDraw( )函数,因此需要在OnDraw( )函数中,根据文档类中数组对象何保存的数据恢复直线。代码如下:
(注意,此函数在生成时就已有,直接在其内添加即可!)
5 文档数据的删除
当初始化新文档之前,如通过“文件”->“新建”菜单命令项创建一个新的文档,必须删除存放在当前文档中的数据。这就需要在文档类中重载函数DeleteContents( )来实现。可以通过ClassWixard在文档类中重载DeleteContents( ),实现代码如下:
6 添加“撤消”菜单命令项入处理
在“Resource View”选项中,单击“Menu”资源中的“IDR_MAINFRAME”菜单资源,在其中添加“编辑”主菜单项,在其下添加“撤消”菜单命令项,ID设置为“ID_UNDO”,其余属性项采用默认置。如下所示:
采用ClassWizard,在文档类SDocDemoDoc中,分别为菜单项添加COMMAND 的UPDATE_COMMAND_UI消息处理函数 OnUndo( ) 和 OnUpdateUndo(),实现如下:
7 编译运行
由于文档中存放有所绘制的直线,窗口缩放和移动时,视图始终显示所绘制的图形,同时还可以通过“撤消”菜单命令项取消最后一步的绘图操作,运行结果如下图:
由于每移动一下鼠标,就会记录下一小段直线对象,所以需多次撤消,才能明显看出。
更改点,每次鼠标左键松开时,再加一标识对象,当撤消时,一次撤消到此标识对象为止。