1、Visual Studio C+ 2010-MFC编程入门之前言 鸡啄米的 C+编程入门系列给大家讲了 C+的编程入门知识,大家对 C+语言在 语法和设计思想上应该有了一定的了解了。但是教程中讲的例子只是一个个简单的例 程,并没有可视化窗口。鸡啄米在这套 VS2010/MFC编程入门教程中将会给大家讲解 怎样使用 VS2010进行可视化编程,也就是基于窗口的程序。 C+编程入门系列主要偏重于理论方面的知识,目的是让大家打好底子,练好内 功,在使用 VC+编程时不至于丈二和尚摸不着头脑。本套教程也会涉及到 VC+的 原理性的东西,同样更重视实用性,让大家学完本套教程以后,基本的界面程序都能 很容
2、易编写出来。 VC+简介 VC+全称是 Visual C+,是由微软提供的 C+开发工具,它与 C+的根本区别 就在于,C+是语言,而 VC+是用 C+语言编写程序的工具平台。VC+不仅是一个 编译器更是一个集成开发环境,包括编辑器、调试器和编译器等,一般它包含在 Visual Studio中。Visual Studio包含了 VB、VC+、C#等编译环境。当然我们在使用 VC+ 6.0的时候为了轻便,总是只单独安装 VC+ 6.0。但自微软 2002年发布 Visual Studio.NET以来,微软建立了在.NET框架上的代码托管机制,一个项目可以支持多 种语言开发的组件,VC+同样被扩展
3、为支持代码托管机制的开发环境,所以.NET Framework是必须的,也就不再有 VC+的独立安装程序,不过可以在安装 Visual Studio时只选择 VC+进行安装。 VC+版本的选择:VS2010 因为 VC+ 6.0以后的版本不再有独立的安装程序,所以鸡啄米在教程中将不会 称 VC+ 6.0以后的版本为 VC+ 7.0等等,而是用 VC+所属的 Visual Studio的版本 名称代替,比如 VS2003。 近些年 VC+主要的版本包括:VC+ 6.0、VS2003、VS2005、VS2008和 VS2010。 VC+ 6.0占用的系统资源比较少,打开工程、编译运行都比较快,所以
4、赢得很多 软件开发者的青睐。但因为它先于 C+标准推出,所以对 C+标准的支持不太好。举 个例子: for(int i=0; i5; i+) ai = i; for语句中声明的变量 i,对于 VC+ 6.0来说,出了 for循环仍能使用。但很显然 这与 C+标准对于变量生存期的规定不符合。 随着 VC+版本的更新,对 C+标准的支持越来越好,对各种技术的支持也越来 越完善。但同时新版本所需的资源也越来越多,对处理器和内存的要求越来越高。到 VS2010,光安装文件就 2G多,安装后的文件占 3G多空间,其运行也经常受处理器 和内存等性能的限制。但鸡啄米还是推荐大家使用 VS2010,毕竟它是最
5、新版本,类 库和开发技术都是最完善的,本教程也将使用 VS2010为大家做例程的演示。当然如 果系统配置确实比较低,可以选择 VS2005,VS2005和 VS2010相比还是要轻量级一 些的。VC+ 6.0已经过时,奉劝大家尽量别用了。 VC+与 MFC 讲 VC+免不了要提 MFC,MFC全称 Microsoft Foundation Classes,也就是微软 基础类库。它是 VC+的核心,是 C+与 Windows API的结合,很彻底的用 C+封装 了 Windows SDK(Software Development Kit,软件开发工具包)中的结构和功能,还 提供了一个应用程序框架
6、,此应用程序框架为软件开发者完成了一些例行化的工作, 比如各种窗口、工具栏、菜单的生成和管理等,不需要开发者再去解决那些很复杂很 乏味的难题,比如每个窗口都要使用 Windows API注册、生成与管理。这样就大大减 少了软件开发者的工作量,提高了开发效率。 当然 VC+不是只能够创建 MFC应用程序,同样也能够进行 Windows SDK编 程,但是那样的话就舍弃了 VC+的核心,放弃了 VC+最强大的部分。MFC也不是 只能用于 VC+中,它同样也可以用在 Borland C+等编译器中,当然没有几个人这样 做。 本节旨在让大家对 VC+、VS2010和 MFC有基本的概念上的认识,后面鸡
7、啄米 会带大家进入 VS2010/MFC的世界,让大家轻松的开发各种包含窗口、图形等的可视 化程序。 一、利用 MFC向导生成单文档应用程序框架 这一讲给大家一个简单的例子,演示如何生成单文档应用程序框架。 解决方案与工程 鸡啄米在 VS2010的使用介绍中已经讲了解决方案与工程的概念,这里再重提一 下。每个应用程序都作为一个工程来处理,它包含了头文件、源文件和资源文件等, 这些文件通过工程集中管理。在 VS2010中,工程都是在解决方案管理之下的。一个 解决方案可以管理多个工程,可以把解决方案理解为多个有关系或者没有关系的工程 的集合。VS2010提供了一个 Solution Explore
8、r解决方案浏览器视图,可以显示当前解 决方案的内容,当新建一个工程时可以选择新建一个解决方案还是加入当前解决方 案。 下图左侧面板中正在显示的视图就是 Solution Explorer,视图中有一个解决方案- HelloWorld,此解决方案下有一个同名的工程-HelloWorld。 在应用程序向导生成应用程序后,VS2010会在用户设置的路径下,以解决方案名 为名称建立一个目录,里面存放自动生成的文件。 使用 VS2010应用程序向导生成单文档应用程序框架 鸡啄米这里简略演示下怎样生成单文档应用程序框架,让大家先有个直观的了 解,有不理解的地方可以留着以后回来再看。下面按照操作步骤一步步讲
9、解: 1.点菜单栏 File-New-Project,弹出 New Project对话框,我们可以选择工程类 型。 如果安装完 VS2010以后第一启动时已经设置为 VC+,则 Installed Templates- Visual C+项会默认展开,而如果没有设置 VC+,则可以展开到 Installed Templates-Other Languages-Visual C+项。因为我们要生成的是 MFC程序,所以在 “Visual C+”下选择“MFC”,对话框中间区域会出现三个选项:MFC ActiveX Control、MFC Application和 MFC DLL。MFC Acti
10、veX Control用来生成 MFC ActiveX 控件程序。MFC Application用来生成 MFC应用程序。MFC DLL用来生成 MFC动态 链接库程序。当然我们要选择 MFC Application。 在对话框下部有 Name、Location和 Solution name三个设置项。意义如下:Name- 工程名,Location-解决方案路径,Solution name-解决方案名称。这里 Name我们设 为“HelloWorld”,Location设置为“桌面”的路径,Solution name默认和 Name一样,当 然可以修改为其他名字,这里我们不作修改,也使用“He
11、lloWorld”。点“OK”按钮。 2.这时会弹出“MFC Application Wizard”对话框,上部写有“Welcome to the MFC Application Wizard”,下面显示了当前工程的默认设置。第一条“Tabbed multiple document interface (MDI)”是说此工程是多文档应用程序。如果这时直接点下面的 “Finish”按钮,可生成具有上面列出设置的多文档程序。但我们此例是要建立单文档应 用程序,所以点“Next”按钮再继续设置吧。 3.接下来弹出的对话框上部写有“Application Type”,当然是让选择应用程序类型, 我们看
12、到有四种类型:Single document(单文档)、Multiple documents(多文档)、 Dialog based(基于对话框)和 Multiple top-level documents。我们选择 Single document 类型,以生成一个单文档应用程序框架。单文档应用程序运行时是一个单窗口界面。 此对话框的“Resource language”还提供语言的选择,这里默认选择英语。“Project style”可选择工程风格,我们选择默认的“Visual Studio”风格。“Use of MFC”有两个选 项:Use MFC in a shared DLL(动态链接库
13、方式使用 MFC)和 Use MFC in a static library(静态库方式使用 MFC)。选择 Use MFC in a shared DLL时 MFC的类会以动 态链接库的方式访问,所以我们的应用程序本身就会小些,但是发布应用程序时必须 同时添加必要的动态链接库,以便在没有安装 VS2010的机子上能够正常运行程序。 选择 Use MFC in a static library时 MFC的类会编译到可执行文件中,所以应用程序的 可执行文件要比上种方式大,但可以单独发布,不需另加包含 MFC类的库。这里我 们使用默认的 Use MFC in a shared DLL。点“Next
14、”按钮。 4.此时弹出上部写有“Compound Document Support”的对话框,可以通过它向应用 程序加入 OLE支持,指定 OLE选项的复合文档类型。本例不需要 OLE特性,使用默 认值“None”。点“Next”按钮。 5.弹出的新对话框上部写有“Document Template Properties”。“File extension”可以设 置程序能处理的文件的扩展名。对话框其他选项还可以更改程序窗口的标题。我们都 使用默认设置,点“Next”按钮。 6.此时弹出的对话框主题是“Database Support”。用于设置数据库选项。此向导可以 生成数据库应用程序需要的代
15、码。它有四个选项: None:忽略所有的数据库支持; Header files only:只包含定义了数据库类的头文件,但不生成对应特定表的数据库 类或视图类; Database view without file support:创建对应指定表的一个数据库类和一个视图 类,不附加标准文件支持; Database view with file support:创建对应指定表的一个数据库类和一个视图类,并 附加标准文件支持。 本例选择默认值“None”,不使用数据库特性。点“Next”按钮。 7.这时弹出的对话框是关于“User Interface Features”,即用户界面特性。我们可以
16、设置有无最大化按钮、最小化按钮、系统菜单和初始状态栏等。还可以选择使用菜单 栏和工具栏生成简单的应用程序还是使用 ribbon。这里我们都选择默认设置。点 “Next”进入下一步。 8.此时弹出“高级特性”对话框。可以设置的高级特性包括有无打印和打印预览等。 在“Number of files on recent file list”项可以设置在程序界面的文件菜单下面最近打开文 件的个数。我们仍使用默认值。点“Next”按钮。 9.弹出“生成类”对话框。在对话框上部的“生成类”列表框内,列出了将要生成的 4 个类:一个视图类(CHelloWorldView)、一个应用类(CHelloWorld
17、App)、一个文 档类(CHelloWorldDoc)和一个主框架窗口类(CMainFrame)。在对话框下面的几 个编辑框中,可以修改默认的类名、类的头文件名和源文件名。对于视图类,还可以 修改其基类名称,默认的基类是 CView,还有其他几个基类可以选择。这里我们还是 使用默认设置。点“Finish”按钮。 应用程序向导最后为我们生成了应用程序框架,并在 Solution Explorer中自动打开 了解决方案(见上面第一张图)。 编译运行生成的程序 点菜单中的 Build-Build HelloWorld编译程序,然后点 Debug-Start Without Debugging(快捷键
18、 Ctrl+F5)运行程序,也可以直接点 Debug-Start Without Debugging,这时会弹出对话框提示是否编译,选择“Yes”,VS2010将自动编译链接运 行 HelloWorld程序。结果页面如下所示: 终于看见界面了。鸡啄米在以后的教程中会继续讲解各种界面和控件的使用方 法。欢迎到鸡啄米博客交流,您的关注是我前进的动力。 二、VS2010应用程序工程中文件的组成结构 鸡啄米在上一讲中为大家演示了如何利用应用程序向导创建单文档应用程序框架。这 一节将以上一讲中生成应用程序 HelloWorld的文件结构为例,讲解 VS2010应用程序 工程中文件的组成结构。 用应用程序
19、向导生成框架程序后,我们可以在之前设置的 Location下看到以解决 方案名命名的文件夹,此文件夹中包含了几个文件和一个以工程名命名的子文件夹, 这个子文件夹中又包含了若干个文件和一个 res文件夹,创建工程时的选项不同,工 程文件夹下的文件可能也会有所不同。 如果已经以 Debug方式编译链接过程序,则会在解决方案文件夹下和工程子文件 夹下各有一个名为“Debug”的文件夹,而如果是 Release方式编译则会有名为“Release” 的文件夹。这两种编译方式将产生两种不同版本的可执行程序:Debug版本和 Release版本。Debug版本的可执行文件中包含了用于调试的信息和代码,而 R
20、elease 版本则没有调试信息,不能进行调试,但可执行文件比较小。 鸡啄米将所有文件分为 6个部分:解决方案相关文件、工程相关文件、应用程序 头文件和源文件、资源文件、预编译头文件和编译链接生成文件。 1.解决方案相关文件 解决方案相关文件包括解决方案文件夹下的.sdf文件、.sln文件、.suo文件和 ipch 文件夹。 .sdf文件和 ipch目录一般占用空间比较大,几十兆甚至上百兆,与智能提示、错 误提示、代码恢复和团队本地仓库等相关。如果你觉得不需要则可以设置不生成它 们,方法是点击菜单栏 Tools-Options,弹出 Options对话框,选择左侧面板中 Text Editor
21、-C/C+-Advanced,右侧列表中第一项 Disable Database由 False改为 True就 可以了,最后关闭 VS2010再删除.sdf文件和 ipch目录以后就不会再产生了。但关闭 此选项以后也会有很多不便,例如写程序时的智能提示没有了。 .sln文件和.suo文件为 MFC自动生成的解决方案文件,它包含当前解决方案中的 工程信息,存储解决方案的设置。 2.工程相关文件 工程相关文件包括工程文件夹下的.vcxproj文件和.vcxproj.filters文件。 .vcxproj文件是 MFC生成的工程文件,它包含当前工程的设置和工程所包含的文 件等信息。.vcxproj.
22、filters文件存放工程的虚拟目录信息,也就是在解决方案浏览器中 的目录结构信息。 3.应用程序头文件和源文件 应用程序向导会根据应用程序的类型(单文档、多文档或基于对话框的程序)自 动生成一些头文件和源文件,这些文件是工程的主体部分,用于实现主框架、文档、 视图等。鸡啄米下面分别简单介绍下各个文件: HelloWorld.h:应用程序的主头文件。主要包含由 CWinAppEx类派生的 CHelloWorldApp类的声明,以及 CHelloWorldApp类的全局对象 theApp的声明。 HelloWorld.cpp:应用程序的主源文件。主要包含 CHelloWorldApp类的实现,
23、CHelloWorldApp类的全局对象 theApp的定义等。 MainFrm.h和 MainFrm.cpp:通过这两个文件从 CFrameWndEx类派生出 CMainFrame类,用于创建主框架、菜单栏、工具栏和状态栏等。 HelloWorldDoc.h和 HelloWorldDoc.cpp:这两个文件从 CDocument类派生出文档 类 CHelloWorldDoc,包含一些用来初始化文档、串行化(保存和装入)文档和调试的 成员函数。 HelloWorldView.h和 HelloWorldView.cpp:它们从 CView类派生出名为 CHelloWorldView的视图类,用来
24、显示和打印文档数据,包含了一些绘图和用于调试 的成员函数。 ClassView.h和 ClassView.cpp:由 CDockablePane类派生出 CClassView类,用于 实现应用程序界面左侧面板上的 Class View。 FileView.h和 FileView.cpp:由 CDockablePane类派生出 CFileView类,用于实现 应用程序界面左侧面板上的 File View。 OutputWnd.h和 OutputWnd.cpp:由 CDockablePane类派生出 COutputWnd类,用 于实现应用程序界面下侧面板 Output。 PropertiesWnd
25、.h和 PropertiesWnd.cpp:由 CDockablePane类派生出 CPropertiesWnd类,用于实现应用程序界面右侧面板 Properties。 ViewTree.h和 ViewTree.cpp:由 CTreeCtrl类派生出 CViewTree类,用于实现出现 在 ClassView和 FileView等中的树视图。 4.资源文件 一般我们使用 MFC生成窗口程序都会有对话框、图标、菜单等资源,应用程序向 导会生成资源相关文件:res目录、HelloWorld.rc文件和 Resource.h文件。 res目录:工程文件夹下的 res目录中含有应用程序默认图标、工具栏
26、使用图标等 图标文件。 HelloWorld.rc:包含默认菜单定义、字符串表和加速键表,指定了默认的 About 对话框和应用程序默认图标文件等。 Resource.h:含有各种资源的 ID定义。 5.预编译头文件 几乎所有的 MFC程序的文件都要包含 afxwin.h等文件,如果每次都编译一次则会 大大减慢编译速度。所以把常用的 MFC头文件都放到了 stdafx.h文件中,然后由 stdafx.cpp包含 stdafx.h文件,编译器对 stdafx.cpp只编译一次,并生成编译之后的预 编译头 HelloWorld.pch,大大提高了编译效率。 6.编译链接生成文件 如果是 Debug
27、方式编译,则会在解决方案文件夹和工程文件夹下都生成 Debug子 文件夹,而如果是 Release方式编译则生成 Release子文件夹。 工程文件夹下的 Debug或 Release子文件夹中包含了编译链接时产生的中间文 件,解决方案文件夹下的 Debug或 Release子文件夹中主要包含有应用程序的可执行 文件。 关于应用程序工程文件的组成结构鸡啄米就先讲到这了。其中包含了很多专有名 词,以后大家会慢慢熟悉的。欢迎来鸡啄米博客交流。谢谢。 三、MFC应用程序框架分析 上一讲鸡啄米讲的是 VS2010应用程序工程中文件的组成结构,可能大家对工程的 运行原理还是很模糊,理不出头绪,毕竟跟 C
28、+编程入门系列中的例程差别太大。这 一节鸡啄米就为大家分析下 MFC应用程序框架的运行流程。 一.SDK应用程序与 MFC应用程序运行过程的对比 程序运行都要有入口函数,在之前的 C+教程中都是 main函数,而 Windows应 用程序的入口函数是 WinMain函数,MFC程序也是从 WinMain函数开始的。下面鸡 啄米就给出用 Windows SDK写的“HelloWorld”程序,与应用程序框架进行对比,这样 能更好的了解框架是怎样运行的。Windows SDK开发程序就是不使用 MFC类库,直 接用 Windows API函数进行软件开发。鸡啄米不是要讲解 SDK开发,只是为了对比
29、 而简单介绍,至于 SDK开发可以在大家学完 MFC以后选择是否要研究,一般来说有 简单了解就可以了。 SDK应用程序 首先,给出 Windows SDK应用程序“HelloWorld”的源码: C+代码 1. include 2. 3. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) 4. 5. const static TCHAR appName = TEXT(“Hello world“); 6. WNDCLASSEX myWin; 7. myWin
30、.cbSize = sizeof(myWin); 8. myWin.style = CS_HREDRAW | CS_VREDRAW; 9. myWin.lpfnWndProc = myWndProc; 10. myWin.cbClsExtra = 0; 11. myWin.cbWndExtra = 0; 12. myWin.hInstance = hInstance; 13. myWin.hIcon = 0; 14. myWin.hIconSm = 0; 15. myWin.hCursor = 0; 16. myWin.hbrBackground = (HBRUSH)(COLOR_WINDOW
31、 + 1); 17. myWin.lpszMenuName = 0; 18. myWin.lpszClassName = appName; 19. /Register 20. if (!RegisterClassEx( 21. const HWND hWindow = CreateWindow( 22. appName, 23. appName, 24. WS_OVERLAPPEDWINDOW, 25. CW_USEDEFAULT, 26. CW_USEDEFAULT, 27. CW_USEDEFAULT, 28. CW_USEDEFAULT, 29. 0, 30. 0, 31. hInsta
32、nce, 32. 0); 33. ShowWindow(hWindow,iCmdShow); 34. UpdateWindow(hWindow); 35. 36. MSG msg; 37. while(GetMessage( 40. DispatchMessage( 41. 42. return (int)msg.wParam; 43. 44. 45. 46. LRESULT CALLBACK myWndProc(HWND hWindow, UINT msg, WPARAM wP aram, LPARAM lParam) 47. 48. if (msg=WM_PAINT) 49. 50. PA
33、INTSTRUCT ps; 51. const HDC hDC = BeginPaint(hWindow, 52. RECT rect; 53. GetClientRect(hWindow, 54. DrawText(hDC,TEXT(“HELLO WORLD“),- 1, 55. EndPaint(hWindow, 56. return 0; 57. 58. else if (msg=WM_DESTROY) 59. 60. PostQuitMessage(0); 61. return 0; 62. 63. return DefWindowProc(hWindow,msg,wParam,lPa
34、ram); 64. 上面的程序运行的流程是:进入 WinMain函数-初始化 WNDCLASSEX,调用 RegisterClassEx函数注册窗口类-调用 ShowWindow和 UpdateWindow函数显示并更 新窗口-进入消息循环。关于消息循环再简单说下,Windows应用程序是消息驱动 的,系统或用户让应用程序进行某项操作或完成某个任务时会发送消息,进入程序的 消息队列,然后消息循环会将消息队列中的消息取出,交予相应的窗口过程处理,此 程序的窗口过程函数就是 myWndProc函数,窗口过程函数处理完消息就完成了某项 操作或任务。本例是要显示“HELLO WORLD”字符串,Upd
35、ateWindow函数会发送WM_PAINT消息,但是此消息不经过消息队列而是直接送到窗口过程处理,在窗口 过程函数中最终绘制了“HELLO WORLD”字符串。 MFC应用程序 下面是 MFC应用程序的运行流程,通过 MFC库中代码进行分析: 首先在 HelloWorld.cpp中定义全局对象 theApp:CHelloWorldApp theApp;。调用 CWinApp和 CHelloWorldApp的构造函数后,进入 WinMain函数(位于 appmodul.cpp 中)。 C+代码 1. extern “C“ int WINAPI 2. _tWinMain(HINSTANCE hI
36、nstance, HINSTANCE hPrevInstance, 3. _In_ LPTSTR lpCmdLine, int nCmdShow) 4. #pragma warning(suppress: 4985) 5. 6. / call shared/exported WinMain 7. return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow); 8. 在 TCHAR.h中,有此定义:#define _tWinMain WinMain,所以这里的_tWinMain 就是 WinMain函数。它调用了 AfxWinM
37、ain函数(位于 WinMain.cpp中)。 C+代码 1. int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LP TSTR lpCmdLine, int nCmdShow) 2. 3. .略 4. / App global initializations (rare) 5. if (pApp != NULL 7. 8. if (!pThread-InitInstance() 9. 10. .略 11. 12. 13. / Run函数位于 THRDCORE.cpp中,由此函数进入消息循环 14. nRetu
38、rnCode = pThread-Run(); 15. 16. 略 17. 18. return nReturnCode; 19. 上面 InitInstance函数的代码如下: C+代码 1. BOOL CTestApp:InitInstance() 2. 3. .略 4. CSingleDocTemplate* pDocTemplate; 5. pDocTemplate = new CSingleDocTemplate( 6. IDR_MAINFRAME, 7. RUNTIME_CLASS(CTestDoc), 8. RUNTIME_CLASS(CMainFrame), / main SD
39、I frame window 9. RUNTIME_CLASS(CTestView); 10. if (!pDocTemplate) 11. return FALSE; 12. AddDocTemplate(pDocTemplate); 13. / Parse command line for standard shell commands, DDE, file open 14. 15. CCommandLineInfo cmdInfo; 16. ParseCommandLine(cmdInfo); 17. 18. /ProcessShellCommand位于 AppUI2.cpp中,注册并创
40、建窗口 19. if (!ProcessShellCommand(cmdInfo) 20. return FALSE; 21. 22. m_pMainWnd-ShowWindow(SW_SHOW); 23. m_pMainWnd-UpdateWindow(); 24. 25. return TRUE; 26. InitInstance中的 ProcessShellCommand函数又调用了 CMainFrame的 LoadFrame函 数注册并创建了窗口,执行完 ProcessShellCommand函数以后,调用了 m_pMainWnd 的 ShowWindow和 UpdateWindow函
41、数显示并更新框架窗口。这些是不是与上面的 SDK程序十分类似? 接下来该是消息循环了,上面的 AfxWinMain函数中调用了 pThread的 Run函数 (位于 THRDCORE.cpp中),在 Run中包含了消息循环。Run函数的代码如下: C+代码 1. int CWinThread:Run() 2. 3. .略 4. / phase2: pump messages while available 5. do 6. 7. / pump message, but quit on WM_QUIT 8. if (!PumpMessage() 9. return ExitInstance();
42、 10. 11. / reset “no idle“ state after pumping “normal“ message 12. if (IsIdleMessage( 15. 16. lIdleCount = 0; 17. 18. 19. while (:PeekMessage( 20. 略 21. 22. 23. BOOL CWinThread:PumpMessage() 24. 25. return AfxInternalPumpMessage(); 26. 27. 28. BOOL AFXAPI AfxInternalPumpMessage() 29. 30. _AFX_THREA
43、D_STATE *pState = AfxGetThreadState(); 31. 32. if (!:GetMessage( 44. 我们看到 PumpMessage中通过调用 GetMessage、TranslateMessage、 DispatchMessage等建立了消息循环并投递消息。 窗口过程函数 AfxWinProc形式如下: C+代码 1. LRESULT CALLBACK AfxWndProc(HWND hWnd,UINT nMsg,WPARAM wPar am, LPARAM lParam) 2. 3. 4. CWnd*pWnd=CWnd:FromHandlePerman
44、ent(hWnd); 5. ReturnAfxCallWndProc(pWnd,hWnd,nMsg,wParam,lParam); 6. 两者运行过程对比 到此,通过对比可以发现,MFC应用程序的运行流程与 SDK程序是类似的,都 是先进行一些初始化过程,再注册并创建窗口,然后显示、更新窗口,最后进入消息 循环,消息都由窗口过程函数处理。现在大家是不是觉得有些头绪了?在运行流程上 有基本的掌握即可。 二.MFC应用程序框架主要类之间的关系 在第二讲中,给大家演示了如何利用应用程序向导生成单文档应用程序框架,可 以看到程序的基本框架和必要的代码都自动生成了,上一讲又讲解了文件组成结构, 实际上在
45、前面自动生成的框架中比较重要的类包括以下几个:CHelloWorldApp、 CMainFrame、CHelloWorldDoc和 CHelloWorldView,至于其他的类比如 CClassView、CFileView等都是在框架窗口(CMainFrame)上创建的面板等,不是必 要的。 鸡啄米就四个主要类的关系简单讲下,CHelloWorldApp类处理消息,将收到的消 息分发给相应的对象。CMainFrame是视图 CHelloWorldView的父窗口,视图 CHelloWorldView就显示在 CMainFrame的客户区中。视图类 CHelloWorldView用来 显示文档类
46、 CHelloWorldDoc中的数据,并根据对视图类的操作修改文档类的数据。一个视图类只能跟一个文档类相联系,而一个文档类可以跟多个视图类相联系。关于 视图类和文档类的关系后面会详细讲解。 本节 VC+/MFC编程入门教程内容比较多,主要是让大家对 MFC应用程序的运 行原理有大概的了解。对于以后的 MFC开发有很多好处。如果有问题请在鸡啄米博 客留言交流。谢谢。 四、MFC消息映射机制概述 上一讲鸡啄米为大家简单分析了 MFC应用程序框架,这一讲是关于 MFC消息映射 机制的内容。 前面已经说过,Windows应用程序是消息驱动的。在 MFC软件开发中,界面操作 或者线程之间通信都会经常用
47、到消息,通过对消息的处理实现相应的操作。比较典型 的过程是,用户操作窗口,然后有消息产生,送给窗口的消息处理函数处理,对用户 的操作做出响应。 什么是消息 窗口消息一般由三个部分组成:1.一个无符号整数,是消息值;(2)消息附带的 WPARAM类型的参数;(3)消息附带的 LPARAM类型的参数。其实我们一般所说的 消息是狭义上的消息值,也就是一个无符号整数,经常被定义为宏。 什么是消息映射机制 MFC使用一种消息映射机制来处理消息,在应用程序框架中的表现就是一个消息 与消息处理函数一一对应的消息映射表,以及消息处理函数的声明和实现等代码。当 窗口接收到消息时,会到消息映射表中查找该消息对应的
48、消息处理函数,然后由消息 处理函数进行相应的处理。SDK编程时需要在窗口过程中一一判断消息值进行相应的 处理,相比之下 MFC的消息映射机制要方便好用的多。 Windows消息分类 先讲下 Windows消息的分类。Windows消息分为系统消息和用户自定义消息。 Windows系统消息有三种: 1.标准 Windows消息。除 WM_COMMAND外以 WM_开头的消息是标准消息。 例如,WM_CREATE、WM_CLOSE。 2.命令消息。消息名为 WM_COMMAND,消息中附带了标识符 ID来区分是来自 哪个菜单、工具栏按钮或加速键的消息。 3.通知消息。通知消息一般由列表框等子窗口发送给父窗口,消息名也是 WM_COMMAND,其中附带了控件通知码来区分控件。 CWnd的派生类都可以接收到标准 Windows消息、通知消息和命令消息。命令消 息还可以由文档类等接收。 用户自定义消息是实际上就是用户定义一个宏作为消息,此宏的值应该大于等于 W