MFC单文档视图程序简介

时间:2020-12-05 03:17:06

在视图应用程序中,应用程序的数据由文档对象代表,数据的视图由视图对象代表。MFC的Cdocument类是文档对象的基类,Cview类是视图对象的基类。应用程序的主窗口,其操作功能在MFC的CframeWnd和CMDIFrameWnd类中实现,已经不再以消息处理为工作焦点了,主要用作视图、工具栏以及其他用户界面对象的容器。

单文档界面应用程序只支持打开一个文档。

1、  文档、视图基础知识。

 

图1展示了SDI文档、视图应用程序的示意图。框架窗口是应用程序的顶层窗口,通常带有WS_OVERLAPPEDWINDOW样式的窗口,带有可缩放边框、标题栏等按钮。视图是子窗口,大小与框架窗口相适应,实际中作为框架窗口的客户区。应用程序的数据保存在文档对象中,数据的可视化表示保存在在视图中。对于一个SDI应用程序,框架窗口类是从CframeWnd派生来的,文档类是从Cdocument派生来的,而视图类是从Cview或相关类派生而来的。

MFC单文档视图程序简介

图1

文档视图应用程序不会为框架窗口获取客户区设备描述表,而是获得视图的设备描述表并在视图中绘制输出。

2、 文档对象、视图对象、框架窗口对象

2.1 文档对象

在文档视图体系结构中,数据被保存在文档对象中,文档对象在主结构初始化时从Cdocument派生出的类时创建的。这里的文档是广义的,泛指能够保存和处理数据的东西。

通常文档对象为其他对象,主要是视图提供了公用成员函数,使用它可以访问文档的数据。所有数据的处理都由文档对象自己完成。

Cdocument中最常用的两个非虚拟类成员函数是SetModifiedFlag和UpdateAllViews。前者设置或清除文档中已经修改的标志,该标志说明文档是否包含没有保存的数据,通常情况下修改了文档数据之后都要调用该函数。UpdateAllViews命令所有与文档关联的视图更新它们自己。实际上,是UpdateAllViews调用每个视图的OnUpdate函数,其默认操作是使视图无效实现重绘。

Cdocument中还有一些虚函数经常被覆盖。

OnNewDocument,在新文档被创建时,由主结构调用,覆盖它是为了每次创建新文档对象时都对文档对象应用专门的初始化。

OnOpenDocument,在从磁盘上装载文档时,由主结构调用。覆盖它是为了每次装载新文档时都对文档对象应用专门的初始化。

DeleteContents,主结构调用它来删除文档的内容。覆盖它是为了在文档关闭之前释放分配给文档的内存和其他资源。

Serialize,主结构调用它在文档和磁盘之间串行化输出或输入,覆盖它是为了提供针对文档的串行化程序一边文档可以被装载和保存。

通常情况下,文档对象只会在应用程序启动时初始化一次,通过OnNewDocument和OnOpenDocument函数我们可以实现对文档对象的重新初始化。一般来说,MFC应用程序更经常覆盖OnNewDocument而不是OnOpenDocument,因为后者间接调用了Serialize函数,Serialize函数初始化文档的永久数据成员,而如果你用非永久数据成员时,你可以在OnOpenDocument函数中初始化。当你想在新文档被创建时初始化,那么就需要覆盖OnNewDocument函数。在文档被创建或打开前,主结构调用DeleteContents函数删除文档对象的数据。当文档打开或者关闭时会调用Serialize函数将文档的数据写入或写出。

2.2 视图对象

文档对象的任务就是管理应用程序的数据,视图对象就有两个用途:提供文档的可视化表示;将用户输入转换为操作文档数据的命令。视图对象包括了Cview及其派生出来的一系列类,比如CscrollView类。一个文档对象可以对应多个视图对象,但是一个视图对象只能有一个文档对象。通过GetDocument函数我们可以获得自己的文档对象。

Cview中同样包含了几个主要的可覆盖函数。OnDraw,主结构创建CpaintDC对象,并使用该对象调用视图的OnDraw函数。OnInitialUpdate函数在视图第一次附加到文档时被调用,覆盖是为了每次在文档被创建或装载时都初始化视图对象。视图对象也只在程序初始化时构造一次,然后重复使用。在SDI中,每当文档被打开或者创建时,都要调用OnInitialUpdate函数。该函数默认调用OnUpdate。我们可以使用OnInitialUpdate函数初始化视图类的数据成员。UpdateAllViews调用OnUpdate,通常我们覆盖OnUpdate函数让其只重绘更新部分而不是整个视图。

2.3 框架窗口对象

SDI应用程序只有一个框架窗口CframeWnd,用作顶层视图并用来包含视图。在MDI应用应用程序中CMDIFrameWnd用作顶层窗口,CMDIChildWnd窗口在顶层窗口中浮动用来包含应用程序文档的视图。

2.4 总结

整个应用程序中,文档对象最先初始化,之后是框架窗口对象,最后才是视图对象。

3、命令传送过程以及预定义命令ID和命令处理程序

3.1 命令传送过程

框架首先会将消息发送给活动视图处理,如果没有处理视图就会发送给对应的文档对象处理。如果文档对象没有处理,那么该消息会传递给文档模板,接着是框架窗口,最后是应用程序对象。如果都没有处理,那么该消息将被::DefWindowProc函数处理。

记住,只有命令消息和用户界面消息才是这样传递的。标准的Windows消息WM_xxx必须在接收这些消息的窗口中处理,鼠标键盘消息传递给视图,其他的基本上给框架窗口。文档对象和应用程序对象不接收非命令消息。

3.2 预定义的命令ID和命令处理程序

CwinApp、Cdocument、CframeWnd和其他MFC类为常用菜单命令提供了默认处理程序。比如,菜单中的退出选项是默认添加的。你完全可以自己创建和设计自定义的命令ID,并提供消息映射表输入项来关联自己的命令ID和默认的命令处理程序。