资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,第,3,章,MFC,基本应用程序的建立,3.1 Windows,编程基础,编制一个功能强大和易操作的,Windows,应用程序所需要的代码肯定会比一般的,C+,程序要多得多,但并不是所有的代码都需要自己从头开始编写,因为,Visual C+,不仅提供了常用的,Windows,应用程序的基本框架,而且可以在框架程序中直接调用,Win32,API(Application,Programming,Interface,应用程序接口,),函数。这样,用户仅需要在相应的框架位置中添加自己的代码或修改部分代码就可实现,Windows,应用程序的许多功能。,3.1.1,简单的,Windows,应用程序,先来看一个最简单的,Windows,应用程序,Ex_HelloMsg,。,例,Ex_HelloMsg,一个简单的,Windows,应用程序,#include ,int,WINAPI,WinMain,(HINSTANCE,hInstance, HINSTANCE,hPrevInstance,LPSTR,lpCmdLine,int,nCmdShow,),MessageBox,(NULL, ,你好,我的,Visual C+,世界!, ,问候, 0) ;,return 0 ;,在,Visual C+ 6.0,运行上述程序需要进行以下步骤:,(1),选择“文件”“新建”菜单命令,显示出“新建”对话框。在“工程”标签页面的列表框,中,选中,Win32 Application,项。,(2),在工程编辑框中键入,Win32,应用程序项目名称,Ex_HelloMsg,。在“位置”编辑框中直,接键入文件夹名称,或单击浏览按钮选择一个已有的文件夹。,(3),单击,确定,按钮继续。一个询问项目类型的,Win32,应用程序向导将被显示,选中,An,empty project,项。单击,完成,按钮,系统将显示该应用程序向导的创建信息,单击,确,定,按钮系统将自动创建此应用程序。,(4),再次选择“文件”“新建”菜单命令,显示出“新建”对话框。在“文件”标签页面左边的,列表框中选择,C+ Source File,项,在右边的文件框中键入,Ex_HelloMsg.cpp,,单击,确定,按钮。,3.1.1,简单的,Windows,应用程序,例,Ex_HelloMsg,一个简单的,Windows,应用程序,(5),输入上面的代码,运行程序,结果如图,3.1,所示。,从上面的程序可以看出:,C+,控制台应用程序以,main,函数作为进入程序的初始入口点,但在,Windows,应用程,序中,,main,主函数被,WinMain,函数取代。,WinMain,函数的原型如下:,int,WINAPI,WinMain,(,HINSTANCE,hInstance,/,当前实例句柄,HINSTANCE,hPrevInstance,/,前一实例句柄,LPSTR,lpCmdLine,/,指向命令行参数的指针,int,nCmdShow,),/,窗口的显示状态,图,3.1,Ex_HelloMsg,运行结果,3.1.1,简单的,Windows,应用程序,所谓句柄是一个标识,Windows,资源,(,如菜单、图标、窗口等,),和设备等对象的数据指针类型。通常,一个句柄变量可用来对系统中某些资源的间接引用。,每一个,C+ Windows,应用程序都需要,Windows.h,头文件,它还包含了其他的一些,Windows,头文件。这些头文件定义了,Windows,的所有数据类型、函数调用、数据结构和符号常量。,程序中,,MessageBox,是一个,Win32 API,函数,用来弹出一个消息对话框。该函数第一个参数用来指定父窗口句柄,即对话框所在的窗口句柄。第二、三个参数分别用来指定显示的消息内容和对话框窗口的标题,最后一个参数用来指定在对话框中显示的按钮。,3.1.1,简单的,Windows,应用程序,例,Ex_HelloWin,一个完整的,Windows,应用程序,#include ,LRESULT CALLBACK,WndProc,(HWND, UINT, WPARAM, LPARAM);/,窗口过程,int,WINAPI,WinMain,(HINSTANCE,hInstance, HINSTANCE,hPrevInstance,LPSTR,lpCmdLine,int,nCmdShow,),HWND,hwnd,;/,窗口句柄,MSG,msg,;/,消息,WNDCLASS,wndclass,;/,窗口类,wndclass.style,= CS_HREDRAW | CS_VREDRAW ;,wndclass.lpfnWndProc,=,WndProc,;,wndclass.cbClsExtra,= 0 ;,wndclass.cbWndExtra,= 0 ;,wndclass.hInstance,=,hInstance,;,wndclass.hIcon,=,LoadIcon,(NULL, IDI_APPLICATION) ;,wndclass.hCursor,=,LoadCursor,(NULL, IDC_ARROW) ;,wndclass.hbrBackground,= (HBRUSH),GetStockObject,(WHITE_BRUSH) ;,wndclass.lpszMenuName,= NULL ;,wndclass.lpszClassName,= ,HelloWin,;/,窗口类名,if (!,RegisterClass,(&,wndclass,),/,注册窗口,MessageBox,(NULL, ,窗口注册失败!, ,HelloWin, 0) ;,return 0 ;,hwnd,=,CreateWindow,(,HelloWin, /,窗口类名,我的窗口,/,窗口标题,WS_OVERLAPPEDWINDOW, /,窗口样式,CW_USEDEFAULT, /,窗口最初的,x,位置,CW_USEDEFAULT, /,窗口最初的,y,位置,CW_USEDEFAULT, /,窗口最初的,x,大小,CW_USEDEFAULT, /,窗口最初的,y,大小,NULL, /,父窗口句柄,NULL, /,窗口菜单句柄,hInstance, /,应用程序实例句柄,NULL) ; /,创建窗口的参数,ShowWindow,(,hwnd,nCmdShow,) ;/,显示窗口,UpdateWindow,(,hwnd,) ;/,更新窗口,包括窗口的客户区,/,进入消息循环:当从应用程序消息队列中检取的消息是,WM_QUIT,时,则退出循环。,while (,GetMessage,(&,msg, NULL, 0, 0),TranslateMessage,(&,msg,) ;/,转换某些键盘消息,DispatchMessage,(&,msg,) ;/,将消息发送给窗口过程,这里是,WndProc,return,msg.wParam,;,LRESULT CALLBACK,WndProc,(HWND,hwnd, UINT message,WPARAM,wParam, LPARAM,lParam,),switch (message),case WM_CREATE: /,窗口创建产生的消息,return 0 ;,case WM_LBUTTONDOWN:,MessageBox,(NULL, ,你好,我的,Visual C+,世界!, ,问候, 0) ;,return 0 ;,case WM_DESTROY:/,当窗口关闭时产生的消息,PostQuitMessage,(0) ;,return 0 ;,return,DefWindowProc,(,hwnd, message,wParam,lParam,) ; /,执行默认的消息处理,3.1.1,简单的,Windows,应用程序,例,Ex_HelloWin,一个完整的,Windows,应用程序,程序运行后,单击鼠标左键,就会弹出一个对话框,结果如图,3.2,所示。,图,3.2,Ex_HelloWin,运行结果,3.1.1,简单的,Windows,应用程序,窗口过程函数,WndProc,用来接收和处理各种不同的消息,而主函数,WinMain,通常要完成以下几步工作:,(1),调用,API,函数,RegisterClass,注册应用程序的窗口类。,(2),调用相关,API,函数创建和显示窗口,并进行其它必要的初始化处理。其中,函数,CreateWindow,用来创建已注册窗口类的窗口。,Windows,每一个窗口都有一些基本属性,如窗口标题、窗口位置和大小、应用程序图标、鼠标指针、菜单和背景颜色等。窗口类就是充当这些属性的模板。,(3),创建和启动应用程序的消息循环。,Windows,应用程序接受各种不同的消息,包括键盘消息、鼠标以及窗口产生的各种消息。,Windows,系统首先将消息放入消息队列中,应用程序的消息循环就是从应用程序的消息队列中检取消息,并将消息发送相应的窗口过程函数中作进一步处理。,API,函数,GetMessage,和,DispatchMessage,就是起到这样的作用。,(4),如果接收到,WM_QUIT,消息,则退出应用程序。,3.1.1,简单的,Windows,应用程序,初始化应用程序,开始执行,初始化并创建,应用程序窗口,进入消息循环,并获取一条消息,消息是否为,WM_QUIT?,终止程序,是,应用程序中是否,处理了此消息,否,处理消息,转送消息给窗口,进行默认处理,是,否,图,3.3 Windows,应用程序的基本流程,3.1.2 Windows,编程特点,一个完整的,Windows,应用程序除了,WinMain,函数外,还包含用于处理用户动作和,窗口消息的窗口函数。这不同于一个,C+,的控制台应用程序,可以将整个程序包,含在,main,函数中。事实上,它们的区别还远不止这些,不久还会发现一个,Windows,应用程序还常常具有这样的一些特性:,消息驱动机制,图形设备接口,(GDI),基于资源的程序设计,动态链接库,进程和线程,3.1.2 Windows,编程特点,1.,消息驱动机制,在,Windows,操作环境中,无论是系统产生的动作或是用户运行应用程序产生的动,作,都称为事件,(Events),产生的消息,(Message),。例如,在,Windows,桌面,(,传统风,格,),上,双击应用程序的快捷图标,系统就会执行该应用程序。在,Windows,的应,用程序中,也是通过接收消息、分发消息、处理消息来和用户进行交互的。,这种消息驱动的机制是,Windows,编程的最大特点。需要注意的是,许多,Windows,消息都经过了严格的定义,并且适用于所有的应用程序。例如,当用户按下鼠标,的左键时系统就会发送,WM_LBUTTONDOWN,消息,而当用户敲了一个字符键时,系统就会发送,WM_CHAR,消息,若用户进行菜单选择或工具按钮单击等操作时,,系统又会相应地发送,WM_COMMAND,消息给相应的窗口等等。,3.1.2 Windows,编程特点,2.,图形设备接口,(GDI),在传统的,DOS,环境中,想要在打印机上打印一幅图形是一件非常复杂的事情,因,为用户必须根据打印机类型和指令规则向打印机输送数据。而,Windows,则提供了,一个抽象的接口,称为图形设备接口,(Graphical Device Interface,,简称,GDI),,,使得用户直接利用系统的,GDI,函数就能方便实现输入或输出,而不必关心与系统,相连的外部设备的类型。,3.,基于资源的程序设计,Windows,应用程序常常包含众多图形元素,例如光标、菜单、工具栏、位图、对,话框等,在,Windows,环境下,每一个这样的元素都作为一种可以装入应用程序的,资源来存放。这些资源就像,C+,程序中的常量一样,可以被编辑、修改,也可以,被其他应用程序所共享。,Visual C+ 6.0,中就提供这样的编辑器,可“所见即所,得”地对这些不同类型的资源进行设计、编辑等。,3.1.2 Windows,编程特点,4.,动态链接库,动态链接库提供了一些特定结构的函数,能被应用程序在运行过程中装,入和连接,且多个程序可以共享同一个动态链接库,这样就可以大大节,省内存和磁盘空间。从编程角度来说,动态链接库可以提高程序模块的,灵活性,因为它本身是可以单独设计、编译和调试的。,Windows,提供了应用程序可利用的丰富的函数调用,大多数用于实现其,用户界面和在显示器上显示的文本和图形,都是通过动态链接库来实现,的。这些动态链接库是一些具有,.DLL,扩展名或者有时是,.EXE,扩展名的文,件。,在,Windows,操作系统中,最主要的,DLL,有,KERNEL32.DLL,、,GDI32.DLL,和,USER32.DLL,三个模块。其中,,KERNEL32,用来处理存储器低层功,能、任务和资源管理等,Windows,核心服务;,GDI32,用来提供图形设备接,口,管理用户界面和图形绘制,包括,Windows,元文件、位图、设备描述,表和字体等;而,USER32,负责窗口的管理,包括消息、菜单、光标、计,时器以及其它与控制窗口显示相关的一些功能。,3.1.2 Windows,编程特点,5 .,进程和线程,在,32,位,Windows,多任务操作系统中,采用了进程和线程的管理模式。进程是装入,内存中正在执行的应用程序。进程包括私有的虚拟地址空间、代码、数据及其它,操作系统资源,如文件、管道以及对该进程可见的同步对象等。进程包括了一个,或多个在进程上下文内运行的线程。线程是操作系统分配,CPU,时间的基本实体。,线程可以执行应用程序代码的任何部分,包括当前正在被其它线程执行的那些部,分。同一进程的所有线程共享同样的虚拟地址空间、全局变量和操作系统资源。,在一个应用程序中,可以包括一个或多个进程,每个进程由一个或多个线程构,成。,3.1.3 Windows,基本数据类型,表,3.1,列出了一些在,Windows,编程中常用的基本数据类型。,表,3.1 Windows,常用的基本数据类型,3.1.3 Windows,基本数据类型,表,3.2,列出了常用的预定义句柄,它们的类型均为,void *,,即一个,32,位指针。,表,3. 2 Windows,常用的句柄类型,3.2,编制一个,MFC,应用程序,前面的,Ex_HelloMsg,和,Ex_HelloWin,都是基于,Windows API,的,C+,应用程序。显然,随着应用程序的复杂性,,C+,应用程序代码也必然越复杂。,为了帮助用户处理那些经常使用又复杂繁琐的各种,Windows,操作,,Visual C+,设计了一套基础类库,(Microsoft Foundation Class Library,,简称,MFC),。,MFC,把,Windows,编程规范中的大多数内容封装成为各种类,,使程序员从繁杂的编程中解脱出来,提高了编程和代码效率。,3.2.1,设计一个,MFC,程序,在理解,MFC,机制之前,先来看一个,MFC,应用程序。,例,Ex_HelloMFC,一个,MFC,应用程序,#include / MFC,头文件,class,CHelloApp,: public,CWinApp,/,声明应用程序类,public:,virtual BOOL,InitInstance,();,;,CHelloApp,theApp,; /,建立应用程序类的实例,class,CMainFrame,: public,CFrameWnd,/,声明主窗口类,public:,CMainFrame,(),/,创建主窗口,Create(NULL, ,我的窗口, WS_OVERLAPPEDWINDOW, CRect(0,0,400,300);,protected:,afx_msg,void,OnLButtonDown(UINT,nFlags,CPoint,point);,DECLARE_MESSAGE_MAP(),;,/,消息映射入口,BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd,),ON_WM_LBUTTONDOWN()/,单击鼠标左键消息的映射宏,END_MESSAGE_MAP(),/,定义消息映射函数,void,CMainFrame:OnLButtonDown(UINT,nFlags,CPoint,point),MessageBox,(,你好,我的,Visual C+,世界!, ,问候, 0) ;,CFrameWnd:OnLButtonDown(nFlags, point);,BOOL,CHelloApp:InitInstance,() /,每当应用程序首次执行时都要调用的初始化函数,m_pMainWnd,= new,CMainFrame,();,m_pMainWnd,-,ShowWindow(m_nCmdShow,);,m_pMainWnd,-,UpdateWindow,();,return TRUE;,3.2.1,设计一个,MFC,程序,在,Visual C+ 6.0,运行上述,MFC,程序需要进行以下步骤:,(1),选择“文件”“新建”菜单命令,显示出“新建”对话框。在“工程”标签页面的列表,框中,选中,Win32 Application,项,创建一个,Ex_HelloMFC,空应用程序项目。,(2),再次选择“文件”“新建”菜单命令,显示出“新建”对话框。在文件标签页面左,边的列表框中选择,C+ Source File,项,在右边的文件框中键入,Ex_HelloMFC.cpp,,单击,确定,按钮。,(3),输入上面的代码。选择“工程”“设置”菜单命令,在出现的对话框中选择,“,General”,标签。然后在“,Microsoft Foundation Classes”,组合框中,选择“,Use,MFC in a Shared DLL”,,如图,3.4,所示。单击,确定,按钮。,(4),程序运行后,单击鼠标左键,就会弹出一个对话框,结果同,Ex_HelloWin,。,3.2.1,设计一个,MFC,程序,图,3.4,设置工程属性,3.2.2,理解程序代码,按照,MFC,的消息映射机制,映射一个消息的过程是由三个部分组成的:,(1),在处理消息的类中,使用消息宏,DECLARE_MESSAGE_MAP,声明对消息映射的支,持,并在该宏之前声明消息处理函数。例如前面示例中的:,protected:,afx_msg,void,OnLButtonDown(UINT,nFlags,CPoint,point);,DECLARE_MESSAGE_MAP(),(2),使用,BEGIN_MESSAGE_MAP,和,END_MESSAGE_MAP,宏在类声明之后的地方定,义该类支持的消息映射入口点,所有消息映射宏都添加在这里,当然不同的消息,MFC,都会有不同的消息映射宏。例如:,BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd,),END_MESSAGE_MAP(),其中,,BEGIN_MESSAGE_MAP,带有两个参数,第一个参数用来指定需要支持消息映,射的用户派生类,第二个参数指定该类的基类。,(3),定义消息处理函数。例如:,void,CMainFrame:OnLButtonDown(UINT,nFlags,CPoint,point),MessageBox,(,你好,我的,Visual C+,世界!, ,问候, 0) ;,CFrameWnd:OnLButtonDown(nFlags, point);,3.3,使用,MFC AppWizard,3.3.1,应用程序框架类型,这些类型基本满足了各个层次的用户的需要,但一般地,用户更关心的是,MFC,AppWizard(exe,),应用程序框架,因为它包含用户最常用、最基本的三种应用程序类型:单文档、多文档和基于对话框的应用程序。,表,3.3 MFC AppWizard,创建的应用程序类型,3.3.2,创建一个单文档应用程序,用,MFC,AppWizard(MFC,应用程序向导,),可以方便地创建一个通用的,Windows,单文档应用程,序,其步骤如下。,1.,开始,选择“文件”“新建”菜单,在弹出的“新建”对话框中,可以看到工程标签页面中,显示出一,系列的应用程序项目类型;选择,MFC,AppWizard(exe,),的项目类型,(,该类型用于创建可执行,的,Windows,应用程序,),,将项目工作文件夹定位在“,D:Visual C+ 6.0,程序”,并在工程编辑,框中输入项目名,Ex_SDIHello,,结果如图,3.5,所示。,图,3.5 MFC AppWizard,的“新建”对话框,3.3.2,创建一个单文档应用程序,2.,第一步,单击,确定,按钮,出现如图,3.6,所示的对话框,进行下列选择:,(1),从应用程序类型单个文档,(SDI),、多重文档,(MDI),和基本对话框,(,基于对话框的,应用程序,),中选择“单个文档”。,(2),决定应用程序中是否需要,MFC,的文档视图,(“,文档,/,查看体系结构支持”,),结构的,支持。若不选定此项,则程序中的磁盘文件的打开、保存以及文档和视图的相互,作用等功能需要用户来实现,且将跳过,Step 2Step 5,,直接弹出“,Step 6”,对话,框。一般情况下,应选中此项。,(3),选择资源所使用的语言,这里是“中文,中国,”,。,3.,第二步,单击,下一个,按钮,出现如图,3.7,所示的对话框,让用户选择程序中是否加入数据,库的支持,(,有关数据库的内容将在以后的章节中介绍,),。,图,3.6 MFC AppWizard,的“,Step 1”,对话框,图,3.7 MFC AppWizard,的“,Step 2”,对话框,3.3.2,创建一个单文档应用程序,4.,第三步,单击,下一个,按钮进入下一步,出现如图,3.8,所示的对话框。允许用户在程序中加入复,合文档、自动化、,ActiveX,控件的支持。,5.,第四步,单击,下一个,按钮进入下一步,出现如图,3.9,所示的对话框,对话框的前几项依次确定,对浮动工具条、打印与预览以及通信等特性的支持。,图,3.8 MFC AppWizard,的“,Step 3”,对话框,图,3.9 MFC AppWizard,的“,Step 4”,对话框,3.3.2,创建一个单文档应用程序,6.,第五步,保留以上默认值,单击,下一个,按钮进入下一步。弹出如图,3.10,所示的对话框,这里出现三,个方面的选项,供用户来选择:,(1),应用程序的主窗口是,MFC,标准风格还是窗口左边有切分窗口的浏览器风格;,(2),在源文件中是否加入注释用来引导用户编写程序代码;,(3),使用动态链接库还是静态链接库。,图,3.10 MFC AppWizard,的“,Step 5”,对话框,3.3.2,创建一个单文档应用程序,7.,第六步,保留默认选项,单击,下一步,按钮进行下一步,出现如图,3.11,所示的对话框。在,这里,用户可以对,MFC AppWizard,提供的默认类名、基类名、各个源文件名进,行修改。,单击,完成,按钮出现一个信息对话框,显示出用户在前面几个步骤中作出的选择,内容,单击,确定,按钮系统开始创建,并又回到了,Visual C+ 6.0,的主界面。,8.,编译并运行,到这里为止,用户虽然没有编写任何程序代码,但,MFC AppWizard,已经根据用,户的选择内容自动生成基本的应用程序框架。单击编译工具栏上的运行工具按钮,“”或按快捷键,Ctrl+F5,,系统开始编连并运行生成的单文档应用程序可执行文件,Ex_SDIHello.exe,,运行结果如图,3.12,所示。,菜单栏,工具栏,状态栏,标题栏,文档窗口,图,3.11 MFC AppWizard,的“,Step 6”,对话框,图,3.12,Ex_SDIHello,运行结果,3.3.3 MFC,应用程序项目组织,1.,项目的文件组织,在,Visual C+ 6.0,中,项目中所有的源文件都是采用文件夹的方式进行管理的,它将,项目名作为文件夹名,在此文件夹下包含源程序代码文件,(.,cpp,.h,),、项目文件,(.,dsp,),以,及项目工作区文件,(.,dsw,),等。表,3.4,列出了这些文件类型的的含义。,表,3.4 Visual C+ 6.0,文件类型的含义,3.3.3 MFC,应用程序项目组织,除了上述文件外,还有相应的,Debug(,调试,),或,Release(,发行,),、,Res,(,资源,),等子文,件夹。例如上述创建的单文档应用程序项目,Ex_SDIHello,,其各文件的组织如图,3.13,所示。当然,不同类型的项目的文件类型及数目会有所不同。,Ex_SDIHello,文件夹,Debug,或,Release,文件夹,Res,文件夹,类文件,.,cpp,.h,资源文件,Ex_SDIHello.rc,项目及项目工作区文件,其他文件,编连过程产生的文件,运行文件,Ex_SDIHello.exe,图标文件,Ex_SDIHello.ico,等,工具栏资源,Toolbar.bmp,其他资源,Ex_SDIHello.rc2,等,图,3.13,Ex_SDIHello,项目的文件组织,3.3.3 MFC,应用程序项目组织,2. MFC,类结构,在开发环境中,,Visual C+ 6.0,是通过左边的项目工作区窗口来对项目进行各种管理。项目,工作区窗口包含,3,个页面,它们分别是,ClassView,页、,ResourceView,页和,FileView,页,通过,单击项目区窗口底部的页面标签进行切换。,将,Visual C+ 6.0,项目工作区窗口切换到,ClassView,页面,可以看到,MFC,为单文档应用程序,项目,Ex_SDIHello,自动创建了类,CAboutDlg,、,CEx_SDIHelloApp,、,CEx_SDIHelloDoc,、,CEx_SDIHelloView,和,CMainFrame,。这些,MFC,类之间的继承和派生关系如图,3.14,所示。,图,3.14 MFC,类的基本层次结构,CCmdTarget,CWnd,CDocument,CFrameWnd,CObject,CWinTread,CWinApp,CView,CDialog,及控件,CMDIChildWnd,CMDIFrameWnd,CMiniFrameWnd,3.4,使用类向导,MFC,类向导,(,ClassWizard,),是,Visual C+ 6.0,中又一个非常有用的工具。,它能自动为一个项目添加一个类、进行消息和数据映射、创建,OLE,Automation(,自动化,),属性和方法以及进行,ActiveX,事件处理等。,3.4.1,类向导概述,打开,MFC,类向导可以使用下列几种方法:,(1),选择“查看”“建立类向导”菜单或直接使用,Ctrl+W,快捷键。,(2),在源代码文件的文档编辑窗口中,右击鼠标,从弹出的快捷菜单中选择“建立,类向导”命令。,当,MFC,类向导打开后,就会弹出如图,3.15,所示的,MFC,ClassWizard,对话框。,图,3.15 MFC,ClassWizard,对话框,3.4.1,类向导概述,可以看到,ClassWizard,对话框包含了,5,个标签页面,它们各自含义如下:,Message Maps(,消息映射,),:用来添加、删除和编程处理消息的成员函数。,Member Variables(,成员变量,),:添加或删除与控件相关联的成员变量,(,或称数据,成员,),,以便与控件进行数据交换。这些控件所在的类一般是从,CDialog,、,CPropertyPage,、,CRecordView,或,CDaoRecordView,中派生的类。,Automation(,自动化,),:为支持,Automation,的类,(,如,ActiveX,控件类,),添加属性和方,法。,ActiveX,Events(ActiveX,事件,),:为,ActiveX,控件类添加触发事件的支持。,Class Info(,类信息,),:有关项目中类的其他信息。,一般来说,,MFC,ClassWizard,对话框最前两项是用户最关心的,也是最经常使用,的,因为几乎所有的代码编写都要利用这两个标签项。由于,Member Variables,功,能以后还会详细讨论,因此这里仅讨论,Message Maps(,消息映射,),与类的添加和,删除方法。,3.4.2,消息和消息映射,1.,消息分类,Windows,应用程序中的消息主要有三种类型。,(1),窗口消息,(Windows message),。这类消息主要是指由,WM_,开头的消息,(WM_,COMMAND,除外,),,一般由窗口类和视图类对象来处理。窗口消息往往带有参,数,以标志处理消息的方法。,(2),控件的通知消息,(Control notifications),。当控件的状态发生改变,(,例如用户在控,件中进行输入,),时,控件就会向其父窗口发送,WM_COMMAND,通知消息。应用程,序框架处理控件消息的方法和窗口消息相同,但按钮的,BN_CLICKED,通知消息,除外,它的处理方法与命令消息相同。,(3),命令消息,(Command message),。命令消息主要包括由用户交互对象,(,菜单、工,具条的按钮、快捷键等,),发送的,WM_COMMAND,通知消息。命令消息的处理方式,与其他两种消息不同,它能够被多种对象接收、处理,这些对象包括文档类、文,档模板类、应用程序本身以及窗口和视类等;而窗口消息和控件的通知消息是由,窗口对象接收并处理的,这里的窗口对象是指从,CWnd,中派生的类的对象,它包,括,CFrameWnd,、,CMDIFrameWnd,、,CMDIChildWnd,、,CView,、,CDialog,以及从,这些类派生的对象等。,3.4.2,消息和消息映射,2.,ClassWizard,映射消息的一般方法,在,MFC,中,绝大多数消息都可由,MFC,的,ClassWizard,来映射。将,ClassWizard,对,话框切换到,Message Maps,页面,(,参看图,3.15),,可以看到它有许多选项,如项目,组合框、类组合框等。各项功能说明如表,3.5,所示。,表,3.5,ClassWizard,对话框的,Message Maps,页面功能,3.4.2,消息和消息映射,2.,ClassWizard,映射消息的一般方法,例如,若向,CEx_SDIHelloView,中添加,WM_LBUTTOMDOWN,的消息映射,则可按下列步,骤进行:,(1),按,Ctrl+W,快捷键打开,MFC,ClassWizard,对话框。,(2),在,Class name,组合框中,将类名选定为,CEx_SDIHelloView,。此时,,Object IDs,和,Messages,列表内容会相应的改变。,(3),在,Object IDs,列表框中选定,CEx_SDIHelloView,,而在,Messages,列表中选定,WM_LBUTTOMDOWN,消息。,(4),双击,Messages,列表中的,WM_LBUTTOMDOWN,消息或单击,Add Function,按钮,都会在,CEx_SDIHelloView,类中添加该消息的映射函数,OnLButtonDown,,同时在,Member,funcions,列表中显示这一消息映射函数和被映射的消息,结果如图,3.16,所示。,(5),单击,Edit Code,按钮后,,ClassWizard,对话框退出,并转向文档窗口,定位到,OnLButtonDown,函数源代码处。,(6),添加下列代码:,void,CEx_SDIHelloView:OnLButtonDown(UINT,nFlags,CPoint,point),MessageBox,(,你好,我的,Visual C+,世界!, ,问候, 0) ;,CView:OnLButtonDown(nFlags, point);,(7),这样就完成了一个消息映射过程。程序运行后,在窗口客户区单击鼠标左键,就会弹出,一个消息对话框。,3.4.2,消息和消息映射,图,3.16,映射,WM_LBUTTONDOWN,消息,3.4.2,消息和消息映射,3.,消息映射代码,查看,CEx_SDIHelloView,程序代码,可以发现:,ClassWizard,为,WM_LBUTTOMDOWN,的消息映射作了以下三个方面内容的安排:,(1),在头文件,Ex_SDIHelloView.h,中声明消息处理函数,OnLButtonDown,:,protected:,/,AFX_MSG(CEx_SDIHelloView,),afx_msg,void,OnLButtonDown(UINT,nFlags,CPoint,point);,/AFX_MSG,DECLARE_MESSAGE_MAP(),代码中的,/,AFX_MSG(CEx_SDIHelloView,),和,/AFX_MSG,之间的部分是,ClassWizard,定义的专门用作消息映射函数声明的标记。表示该程序块中的消息映射声明是由,ClassWizard,来自动管理的,用户一般不需要去更改。需要说明的是,凡,/,和,/,之间,的程序代码块均由,ClassWizard,自动管理。,3.4.2,消息和消息映射,3.,消息映射代码,(2),在,Ex_SDIHelloView.cpp,源文件前面的消息映射入口处,添加了相应的映射宏:,BEGIN_MESSAGE_MAP(CEx_SDIHelloView,CView,)/,消息映射开始,/,AFX_MSG_MAP(CEx_SDIHelloView,),ON_WM_LBUTTONDOWN(),/AFX_MSG_MAP,END_MESSAGE_MAP()/,消息映射结束,(3),在,Ex_SDIHelloView.cpp,文件中写入一个空的消息处理函数的模板,以便用户填入,具体代码,如下面的框架:,void,CEx_SDIHelloView:OnLButtonDown(UINT,nFlags,CPoint,point),/ TODO: Add your message handler code here and/or call default,CView:OnLButtonDown(nFlags, point);,事实上,根据,ClassWizard,产生的上述消息映射过程,用户可以自己手动添加一些,MFC,ClassWizard,不支持的消息映射函数,以完成特定的功能。例如,,Ex_HelloMFC,示例就是按照上述过程添加消息映射的。,3.4.2,消息和消息映射,4.,键盘消息,当用户按下一个键或组合键时,,Windows,将,WM_KEYDOWN,或,WM_SYSKEYDOWN,放入具有输入焦点的应用程序窗口的消息队列中。当键被释放时,,Windows,则把,WM_KEYUP,或,WM_SYSKEYUP,消息放入消息队列中。对于字符键来说,还会在这,两个消息之间产生,WM_CHAR,消息。,MFC,ClassWizard,能自动添加了当前类的,WM_KEYDOWN,和,WM_KEYUP,击键消息,处理函数的调用,它们具有下列函数原型:,afx_msg,void,OnKeyDown,( UINT,nChar, UINT,nRepCnt, UINT,nFlags,);,afx_msg,void,OnKeyUp,( UINT,nChar, UINT,nRepCnt, UINT,nFlags,);,afx_msg,是,MFC,用于定义消息函数的标志,参数,nChar,表示虚拟键代码,,nRepCnt,表,示当用户按住一个键时的重复计数,,nFlags,表示击键消息标志。,所谓虚拟键代码,是指与设备无关的键盘编码。在,Visual C+,中,最常用的虚拟键代,码已被定义在,Winuser.h,中,例如:,VK_SHIFT,表示,SHIFT,键,,VK_F1,表示功能键,F1,等。,同击键消息一样,,MFC,中的,ClassWizard,也提供相应的字符消息处理框架,并自动添,加了当前类的,WM_CHAR,消息处理函数调用,它具有下列函数原型:,afx_msg,void,OnChar,( UINT,nChar, UINT,nRepCnt, UINT,nFlags,);,参数,nChar,表示键的,ASCII,码,,nRepCnt,表示当用户按住一个键时的重复计数,,nFlags,表示字符消息标志。,3.4.2,消息和消息映射,5.,鼠标消息,当用户对鼠标进行操作时,像键盘一样也会产生对应的消息。通常,,Windows,只,将键盘消息发送给具有输入焦点的窗口,但鼠标消息不受这种限制。只要鼠标移,过窗口的客户区时,就会向该窗口发送,WM_MOUSEMOVE(,移动鼠标,),消息。,这里的客户区是指窗口中用于输出文档的区域。由于,MFC,头文件中定义的与鼠标,按钮相关的标识使用了,LBUTTON(,左,),、,MBUTTON(,中,),和,RBUTTON(,右,),,因而,当在窗口的客户区中按下或释放一个鼠标键时,还会产生如表,3.6,所示的消息。,表,3.6,客户区鼠标消息,3.4.2,消息和消息映射,5.,鼠标消息,对于所有这些消息来说,,ClassWizard,都会将映射成类似,afx_msg,void,OnXXXX,的消息处理函数,如前面,WM_LBUTTONDOWN,的消息函数,OnLButtonDown,,,它们具有函数原型:,afx_msg,void,OnXXXX,( UINT,nFlags,CPoint,point,);,其中,,point,表示鼠标光标在屏幕的,(,x,y,),坐标;,nFlags,表示鼠标按钮和键盘组合情,况,它可以是下列值的组合,(MK,前缀表示“鼠标键”,),:,MK_CONTROL ,键盘上的,Ctrl,键被按下,MK_LBUTTON ,鼠标左按钮被按下,MK_MBUTTON ,鼠标中按钮被按下,MK_RBUTTON ,鼠标右按钮被按下,MK_SHIFT ,键盘上的,Shift,键被按下,若想知道某个键被按下,可用对应的标识与,nFlags,进行逻辑“与”,(&),运算,所得结,果若为,TRUE(,非,0),时,则表示该键被按下。例如,若收到了,WM_LBUTTONDOWN,消息,且值,nFlags&MK_CONTROL,是,TRUE,时,则表明,按下鼠标左键的同时也按下,Ctrl,键。,3.4.2,消息和消息映射,6.,计时器消息,应用程序是通过,CWnd,的,SetTimer,函数来设置并启动计时器的,这个函数的原型如下:,UINT,SetTimer,(,UINT,nIDEvent,UINT,nElapse,void (CALLBACK,EXPORT*,lpfnTimer,)(HWND,UINT,UINT,DWORD),);,参数,nIDEvent,用来指定该计时器的标识值,(,不能为,0),,当应用程序需要多个计时器时可多次,调用该函数,但每一个计时器的标识值应是唯一的,各不相同。,nElapse,表示计时器的时,间间隔,(,单位为毫秒,),,,lpfnTimer,是一个回调函数的指针,该函数由应用程序来定义,用来,处理计时器,WM_TIMER,消息。一般情况下该参数为,NULL,,此时,WM_TIMER,消息被放入到,应用程序消息队列中供,CWnd,对象处理。,SetTimer,函数成功调用后返回新计时器的标识值。当应用程序不再使用计时器时,可调用,CWnd,:,KillTimer,函数来停止,WM_TIMER,消息的传送,其函数原型如下:,BOOL,KillTimer,(,int,nIDEvent,);,其中,nIDEvent,和用户调用,SetTimer,函数设置的计时器标识值是一致的。,对于,WM_TIMER,消息,,ClassWizard,会将其映射成具有下列原型的消息处理函数:,afx_msg,void,OnTimer,(,UINT,nIDEvent,);,通过,nIDEvent,可判断出,WM_TIMER,是哪个计时器传送的。,3.4.2,消息和消息映射,7.,其他窗口消息,在系统中,除了用户输入产生的消息外,还有许多系统根据应用程序的状态和运,行过程产生的消息,有时也需要用户进行处理。,(1) WM_CREATE,消息。该消息是在窗口对象创建后,,Windows,向视图发送的第,一个消息;如果用户有什么工作需要在初始化时处理,就可在该消息处理函数中,加入所需代码。但是,由于,WM_CREATE,消息发送时,窗口对象还未完成,窗,口还不可见,因此在该消息处理函数,OnCreate,内,不能调用那些依赖于窗口处于完成激活状态的,Windows,函数,如,窗口的绘图函数等。,(2) WM_CLOSE,或,WM_DESTROY,消息。当用户从系统菜单中关闭窗口或者父,窗口被关闭时,,Windows,都会发送,WM_CLOSE,消息;而,WM_DESTROY,消息是,在窗口从屏幕消失后发送的,因此它紧随,WM_CLOSE,之后。,(3) WM_PAINT,消息。当窗口的大小发生变化、窗口内容发生变化、窗口间的层,叠关系发生变化或调用函数,UpdateWindow,或,RedrawWindow,时,系统都将产生,WM_PAINT,消息,表示要重新绘制窗口的内容。该消息处理函数的原型是;,afx_msg,void,OnPaint,();,用,ClassWizard,映射该消息的目的是执行自己的图形绘制代码 。,3.4.3,类的添加和删除,1.,类的添加,给项目添加一个类有很多方法,例如选择“工程”“添加工程”“,Files”,菜单命令,,可将外部源文件所定义的类添加到项目中。但是如果使用,MFC,的,ClassWizard,,,就可以从大多数,MFC,类中派生一个类,并且创建的类代码自动包含,MFC,所必需,的消息映射等机制。,用,MFC,ClassWizard,给项目添加一个类通常是按下列步骤进行的:,(1),按快捷键,Ctrl+W,启动,MFC,ClassWizard,对话框。单击,Add Class,按钮,从弹,出的下拉菜单中选择,New,命令,弹出如图,3.17,所示的,New Class,对话框。,(2),对话框中,,Name,是用来输入用户定义的类名,注意要以“,C”,字母打头,以保,持与,MFC,标识符命名规则一致;,File Name,是该类的源代码文件名,单击,Change,按钮可改变源文件名称及其在磁盘中的位置;,Base class,用来指定该类,的基类;,Dialog ID,是当选择,CDialog,作为基类时指定对话框的资源,ID,号。最下面,的,Automation,是用来设置对自动化的支持。,(3),单击,OK,按钮,一个新类就会自动添加到项目中。,3.4.3,类的添加和删除,图,3.17 New Class,对话框图,1.,类的添加,3.4.3,类的添加和删除,2.,类的删除,当添加的类需要删除时,则需要按下列步骤进行:,将,Visual C+ 6.0,打开的所有文档窗口关闭。,将项目工作区窗口切换到,FileView,页面,展开,Source Files,和,Header Files,结点,,分别选定要删除类的对应,.h,和,.,cpp,文件,按下,Delete,键,删除这两个文件。,选择“文件”“关闭工作区”菜单命令,关闭项目。,从实际的文件夹中删除对应的,.h,和,.,cpp,文件与,.,clw,文件。,这样,当调入项目文件后,按,Ctrl+W,快捷键就会弹出一个对话框,询问是否重新,建立,ClassWizard,数据文件,单击,是,按钮,出现如图,3.18,所示的,Select Source,Files,对话框。单击右下的,Add All,按钮即可将,.h,和,.,cpp,所包含的类删除。,3.4.3,类的添加和删除,2.,类的删除,3.18 Select Source Files,对话框,
展开阅读全文