《【教学课件】第4章文档应用程序.ppt》由会员分享,可在线阅读,更多相关《【教学课件】第4章文档应用程序.ppt(33页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第4章 文档应用程序第3章讲述了如何使用SDK开发窗口应用程序。本章将介绍如何使用MFC开发窗口应用程序。MFC(Microsoft Foundation Classes,微软基础类库)通过面向对象的方式将SDK进行封装,使用户在使用API函数时更加方便简单。使用VC+6.0可以创建下面3种MFC应用程序:单文档应用程序;多文档应用程序;对话框应用程序。单文档程序和多文档程序类似,都是文档应用程序。本章主要介绍单文档应用程序的开发方法,对话框应用程序将会在后面的章节中继续讲解。4.1 使用AppWizard应用程序向导创建单文档程序本节将使用VC+6.0提供的工具AppWizard应用程序向导
2、来创建一个单文档的程序,具体操作步骤如下。4.2 MFC程序框架分析上一节创建的单文档程序的类视图如图4.11所示。当使用应用程序向导创建单文档应用程序完成后,程序中会自动包含5个类,其作用如下。CAboutDlg关于对话框类:管理关于对话框。CEg_1_single_docApp应用程序类:管理整个应用程序。CEg_1_single_docDoc文档类:通常和视图窗口一同使用,后面会介绍。CEg_1_single_docView视图类:管理视图窗口。CMainFrame框架类:管理框架窗口。4.2.1 theApp全局对象theApp是应用程序类CEg_1_single_docApp的全局对
3、象。由于全局对象会在入口函数之前被构造,所以theApp可以使MFC程序在执行WinMain函数之前做一些初始化工作(通过CEg_1_single_docApp父类CWinApp的构造函数完成)。同时,框架中很多地方会用到应用程序类的成员,其生命周期也是从程序开始到程序结束,所以称其为应用程序类。4.2.2 MFC中的WinMain函数MFC程序将WinMain函数的定义封装了起来,原因是MFC希望用户不再关注程序入口,只需处理各种消息即可。实际上,WinMain函数被定义在VC安装目录中的VC98MFCSRCAPPMODUL.CPP文件内(MFC的源代码都存放在VC98MFCSRC目录内),
4、其相应代码如下。extern C int WINAPI_tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)/call shared/exported WinMainreturn AfxWinMain(hInstance,hPrevInstance,lpCmdLine,nCmdShow);4.2.3 窗口的句柄在MFC中,每个窗口都对应一个窗口类。例如框架窗口对应的是CMainFrame类,视图窗口对应的是CEg_1_single_docView。所有的窗口类都是从CWnd派生而来
5、,如图所示。CWnd的成员m_hWnd表示对应窗口的句柄。4.3 框架窗口框架窗口是所有其他窗口的父窗口,使用框架窗口可以轻松地管理其子窗口,如标题栏、菜单栏。CMainFrame框架窗口类用来管理框架窗口。4.3.1 框架窗口的重要成员函数CMainFrame类 中 有 2个 比 较 重 要 的 成 员 函 数,即 OnCreate和PreCreateWindow。通过跟踪调试可以得知,PreCreateWindow会在OnCreate之前被调用。实际上,PreCreateWindow是在创建窗口之前调用的,其参数是一个CREATESTRUCT结构体类型的变量。通过修改这个变量中的字段可以达
6、到预定义窗口样式的作用。实际上,CREATESTRUCT结构体内的字段就是CreateWindow函数所需要的参数。框架代码中PreCreateWindow的默认定义如下。BOOL CMainFrame:PreCreateWindow(CREATESTRUCT&cs)if(!CFrameWnd:PreCreateWindow(cs)return FALSE;/TODO:Modify the Window class or styles here by modifying/the CREATESTRUCT csreturn TRUE;4.3.2 改变窗口状态上一小节介绍过,通过修改PreCrea
7、teWindow函数的参数(CREATESTRUCT结构体变量)可以在窗口创建之前修改窗口的样式。下面介绍一些其他的方法。(1)使用应用程序向导修改窗口样式。前面介绍过,应用程序向导的第4、第5步也可以预先设置窗口的样式。(2)在应用程序类的InitInstance函数中修改窗口显示方式。由于框架窗口的显示是在InitInstance时进行的。(3)窗口创建后样式的改变。如果窗口已经被创建,修改窗口样式就需要使用API函数实现。以下API函数可以修改窗口的一些外观。4.4 文档模板MFC单文档或多文档程序使用文档模板将各个类组织在一起,例如本例在应用程序类的InitInstance函数中创建了
8、文档模板,对应代码如下。BOOL CEg_1_single_docApp:InitInstance()/Register the applications document templates.Document templates/serve as the connection between documents,frame windows and views.CSingleDocTemplate*pDocTemplate;pDocTemplate=new CSingleDocTemplate(IDR_MAINFRAME,RUNTIME_CLASS(CEg_1_single_docDoc),R
9、UNTIME_CLASS(CMainFrame),/main SDI frame windowRUNTIME_CLASS(CEg_1_single_docView);AddDocTemplate(pDocTemplate);4.5 文档的序列化序列化是将用户的数据存储在文件中,并在需要时再从文件中将数据读取出来。与简单的文件读写不同,序列化可以保存数据的类型,甚至将一个类保存在文件中。4.5.1 MFC文档读写机制MFC文档程序中,文档的读写是在文档类中进行的,由文档类的Serialize函数完成,其默认代码如下。void CEg_1_single_docDoc:Serialize(CArch
10、ive&ar)if(ar.IsStoring()/TODO:add storing code hereelse/TODO:add loading code here4.5.2 示例建立可序列化的类上一节讲述了MFC文档程序中文档读写机制序列化(Serialize)。本小节将演示如何创建一个可序列化的MFC类。通常,创建一个可序列化的类的步骤如下。(1)创建一个类(要序列化的类),其父类为CObject。(2)在类的声明文件中添加宏DECLARE_SERIAL(类名)。(3)在类的实现文件中添加宏IMPLEMENT_SERIAL(类名,父类名,版本号)。(4)添加不带参数的构造函数。(5)重写S
11、erialize函数。4.6 文档视图结构文档类与视图类通常在一起使用,文档类管理视图类要显示的内容,视图类负责显示文档类管理的数据。4.6.1 一般视图类的使用当使用应用程序向导创建文档程序时,在应用程序向导第6步可以指定视图类的基类,如图4.8所示。例子中使用的是默认选项,即使用CView作为视图类的基类。此视图类功能有限,选择其他视图类会得到更强大的功能。表为其他常用视图类的介绍。4.6.2 文档与视图的相互访问文档与视图配合使用,彼此之间需要互相访问。(1)文档类访问视图类。POSITION pos=GetFirstViewPosition();while(pos!=NULL)CVie
12、w*pView=GetNextView(pos);if(pView)/获得指针后的操作(2)视图类访问文档类。CView:GetDocument可以返回当前文档类对象的指针(CDocument*类型)。(3)视图类访问主框架。视图类访问主框架可以使用CWnd:GetParentFrame函数。4.6.3 切分窗口如果文档窗口由多个视图拼合组成(类似资源管理器),可以通过切分窗口来完成。MFC文档程序使用CSplitterWnd切分窗口(MFC对话框程序不提供切分功能,无法使用CSplitterWnd类)。切分窗口的一般步骤如下。(1)为CMainFrame添加CSplitterWnd变量。(2
13、)创建新的视图类。(3)重写CMainFrame的OnCreateClient方法。(4)使用CSplitterWnd:CreateStatic将窗口切分成格子。(5)使用CSplitterWnd:CreateView设置格子中要显示的视图。4.7 MFC的编程的核心消息映射MFC程序创建窗口非常容易,甚至不用书写任何代码。消息循环也被框架封装起来了,提供给用户进行开发的接口是消息映射(当指定消息发生时,通过一个消息函数处理,也叫消息处理)。在MFC中添加消息映射有2种方法,即使用类向导创建和手动创建。4.7.1 使用类向导添加消息处理使用Ctrl+W键可以打开类向导对话框。选择“Messag
14、e Maps”选项卡可以切换到消息映射界面,如图所示。4.7.2 手动添加消息映射使用类向导添加的消息映射完全可以手动完成。手动添加消息映射分为三步。(1)在类声明中,添加消息函数声明,消息函数前要有afx_msg宏,用来区分函数是普通函数还是消息函数。(2)在类的实现文件中的BEGIN_MESSAGE_MAP与END_MESSAGE_MAP之间添加消息映射宏,消息映射宏必须定义为ON_MESSAGE(消息ID,消息函数),表示当消息ID代表的消息产生时,使用消息函数处理。(3)编写消息函数。4.8 菜单编程使用菜单可以将程序的各个功能管理起来,为程序界面节省空间,本节介绍菜单编程的方法。4.
15、8.1 使用资源视图设计菜单通过VC+6.0中的资源视图可以查看当前程序中的资源。程序中的资源一般有对话框、快捷键、图标、图片、菜单栏、工具栏、字符串和版本信息等。双击某个资源便可以对其进行可视化编辑。如图所示,双击资源视图内的菜单资源IDR_MAINFRAME,右边的编辑视图会显示出此菜单的可视化界面。右击某个菜单项,在弹出的快捷菜单中选择“Properties”命令,此时会显示菜单项的属性,如图所示。4.8.2 响应菜单消息当用户选择某一菜单项时,会产生一条WM_COMMAND消息,响应菜单消息只需处理菜单项的WM_COMMAND消息即可。继续修改前面的例子,并且演示如何响应菜单的WM_C
16、OMMAND消息,具体操作步骤如下。(1)修改IDR_MAINFRAME菜单资源,添加菜单项。(2)打开类向导,添加IDM_MSGBOX的WM_COMMAND消息。(3)编写OnMsgbox代码如下。void CMainFrame:OnMsgbox():MessageBox(NULL,您选择了“显示信息框”菜单项,提示,MB_OK);4.8.3 更改应用程序菜单更改单文档程序的菜单有2种方式,即直接修改IDR_MAINFRAME菜单资源或新添加菜单资源并重新加载此菜单资源。第1种方式在上一小节已经介绍过,本小节介绍第2种方式,具体操作步骤如下。4.8.4 使用快捷菜单(右键菜单)本小节通过继续
17、修改前面的例子来演示如何显示快捷菜单(右键菜单)。具体操作步骤如下。(1)再次添加新菜单资源,设置其ID为IDM_SEDMENU。(2)编辑菜单效果。(3)添加菜单项IDM_TRACKMENU1与IDM_TRACKMENU2的消息函数,但是需要在“Class name”下拉列表框中选择视图类CEg_3_splitwndView,编写代码如下。void CEg_3_splitwndView:OnTrackmenu1():MessageBox(NULL,您选择了“快捷菜单1”菜单项,提示,MB_OK);void CEg_3_splitwndView:OnTrackmenu2():MessageBo
18、x(NULL,您选择了“快捷菜单2”菜单项,提示,MB_OK);4.9 工具栏编程工具栏经常与菜单栏一起使用。每个工具栏中的按钮就相当于菜单栏中的某个菜单项,当菜单项不可用时,工具栏也不可用;单击某个工具栏按钮就相当于选择了某个菜单项。4.9.1 使用工具栏编辑器工具栏也是一种资源,可以通过资源编辑器来编辑。工具栏的编辑状态如图所示。4.9.2 工具栏菜单结合要使工具栏按钮可用,必须为其指定一个ID,并且此ID必须为已有菜单项的ID。双击某个按钮可以编辑按钮的属性。新建一个工具栏按钮,设计按钮图标如图所示。修改按钮ID为IDM_TEST。程序执行以后的结果如图所示。可以看到,当单击IDM_TE
19、ST按钮时,相当于选择了“测试菜单”“测试”命令。4.9.3 多个工具栏使用本节将通过继续修改前面的示例来介绍工具栏的创建过程,以及如何在程序中使用多个工具栏。首先来了解一下工具栏是如何创建的。工具栏的创建是在CMainFrame:OnCreate时发生的。其相应代码如下。4.10 状态栏编程状态栏通常用来显示程序中的一些状态信息,例如当前时间、文档路径。使用CStatusBar可以操作状态栏。4.10.1 状态栏的定义状态栏通常被分成几个格子,每个格子显示不同的信息,如图所示。图中的状态栏由4个格子组成,分别用来显示工具信息、Caps Lock状态、Num Lock状态和Scroll Lock状态。4.10.2 状态栏的常用操作本小节将通过一个示例来演示一些状态栏的常用操作。具体操作步骤如下。4.11 小结本章主要介绍了单文档程序的开发方法,其中包括了MFC框架流程、框架代码的组织方式、菜单与工具栏、状态栏的使用等。文中还涉及一些CTime类和定时器的相关知识。MFC程序最重要的是面向对象封装,例如CMainFrame类管理框架窗口、CView类管理视图窗口等。用户不需要管理入口函数、窗口创建等操作,只需处理各种消息即可。
限制150内