第十四章 单文档界面的程序
用VC++的AppWizard生成的程序有三种样式的界面,它们是单文档、多文档和对话框界面。前面各章我们都生成对话框样式的界面,这可以方便我们学习各种常用控件的设计,本章要学习如何生成一个单文档界面的应用程序,以及文档类和视图类的概念和相互关系。
本章要点
1 用AppWizard生成单文档界面的操作方法
2 文档类和视图类的概念
3 如何保持文档和视图的同步关联。
14.1 生成单文档界面的文本编辑器
用AppWizard生成单文档界面的操作方法和生成对话框界面的操作方法稍有不同,我们通过建立一个“文本编辑器”应用程序MyNote.exe来演示,具体过程如下:
1 打开应用程序向导,在d:\myVC\CH14创建应用程序MyNote。
2 在Step1中选择“单文档”和“文档/视图支持”,如图chap14-01.
3 在step2和step3对话框中都用默认的。在step4中如图chap14-02选择前五项,当然也可以按你的需要选择。
图chap14-02
4 在Step5中选择MFC标准、加备注和静态连接库。图chap14-03
图chap14-03
5 在step6中选择视图的基类(base class),因为我们需要的是文本编辑器,所以要选类CEditView作为基类。点击[完成]按纽,应用程序的框架就创建好了。
14.2 文档类和视图类的概念
向导工作完成以后马上编译和连接,运行后就可以看到一个已经能够使用的文本编辑器,它不仅可以输入文字,还可以保存或打开文件,与Windows的记事本差不多了,只是没有设置字体的功能。图chap14-04是它运行时的窗口。
菜单和工具栏的响应函数都已经生成了相应的代码,我们没有做任何编写工作就得到了一个“完整”的应用程序,甚至还创建了一个帮助文件呢。这就是VC++开发环境的巨大威力!我们从上图中可以看到,编辑菜单中的复制和剪切都已经有效了。
图中的窗口是主框架,对应于类CMainFrame,而其中的“编辑区域”叫用户区,对应于视图类CMyNoteView,而被编辑的文本对应于一个文档类CMyNoteDoc。另外,每个程序还有一个对应于应用程序本身的类,本例中是CMyNoteApp。这四个类就是向导自动生成的应用程序框架类,打开工作区的类classView页区,就可以看到,如图chap14-05。
展开视图类,可以找到一个函数GetDocument(),它是使视图(的内容)和文档保持同步关联的纽带。它返回一个CMyNoteDoc类型的对象指针m_pDocument。使用它在视图中访问文档的内容。
在文档类中有一个OnNewDocument()函数,在“新建文件”和程序第一次运行时被调用,它打开一个新文档供用户编辑。我们来看一下它的代码:
BOOL CMyNoteDoc::OnNewDocument()
{
}
if语句调用其父类的同名函数,第二个语句设置编辑区的文本为空白。你试着用“这是一个新文档”来代替NULL,重新编译和运行,那每次打开时编辑区会出现这句话。
文档类中还有一个叫Serialize,把它系列化对象CArchive& ar设置为按行系列化,这是纯文本文件存取时所需要的。下面是它的代码。
void CMyNoteDoc::Serialize(CArchive& ar)
{
}
在下一节中,我们将通过一个例程来演示,如何在文档对象和视图对象之间互相访问和交换数据。
14.3 Circle程序的界面和功能
Circle程序的功能是:用鼠标左键在用户区域任意的点一下,就以这一点为圆心画一个半径为50的圆。程序的界面和上例一样,都是单文档程序的基本形式么。但是其客户区年输入文字,是画图形式的。
下面我们就来制作这一程序。
1 创建工程
打开应用程序向导,在d:\myVC\CH14创建应用程序Circle。选择“单文档”,后面的应答与上例一样。不同的是最后一步视图基类的选择,不是选CEditView而是选CView。CEditView类是CView类的子类,适合于需要文字编辑的场合。
2 添加变量
画圆需要与圆心和半径,为了文档和视图的同步,我们需要给两者都引进三个变量m_PosX、 m_PosY和m_Reduse。定义要写在他们的构造函数中:
public:
3 编写代码
(1)函数OnDraw(CDC* pDC)的功能是在客户区画图,我们用它以试图中的变量值来画圆,代码如下:
void CCircleView::OnDraw(CDC* pDC)
{
}
其中pDC是由参数表传递过来的屏幕设备对象,可以画图。RECT是表示举行的数据结构。是画图圆需要的参数。
(2)变量m_PosX等的值在初始更新函数OnInitialUpdate()中给定,而值是从文档的同名函数中传递过来的。
(3)要求当“按下鼠标时画圆”,就要添加OnLButtonDown函数,其中使用Invalidate(),它会调用函数OnDraw重新画客户区,其代码如下:
void CCircleView::OnLButtonDown(UINT nFlags, CPoint point)
{
}
变量point对应的是鼠标当前点的位置,传递给视图的变量,然后画圆;再把它传递给文档,这就保证视图和文档数据的一致性。语句
设置文档已经被修改的标志,这使得程序在退出时会询问“是否要保存?”。
(4)在文档类中有一个函数OnNewDocument(),它是在按“文件/新建”时被调用的。我们用它给出圆的初始值:
需要的代码就这些了,现在可以编译和运行之。
思考和练习
1 文档类应用程序是如何保持视图和文档数据的一致性的?
2 在MyNote程序中添加菜单及其代码,扩展它的功能。例如,增加文字的大小和颜色等。
3 在Circle程序中添加菜单及其代码,扩展它的功能。例如,可变的半径,画不同的图形等。