1、V S2 010/M FC 编程 入门 之前言鸡啄米的 C+编程入门系列给大家讲了 C+的编程入门知识,大家对 C+语言在语法和设计思想上应该有了一定的了解了。但是教程中讲的例子只是一个个简单的例程,并没有可视化窗口。鸡啄米在这套 VS2010/MFC 编程入门教程中将会给大家讲解怎样使用 VS2010 进行可视化编程,也就是基于窗口的程序。C+编程入门系列主要偏重于理论方面的知识,目的是让大家打好底子,练好内功,在使用 VC+编程时不至于丈二和尚摸不着头脑。本套教程也会涉及到 VC+的原理性的东西,同样更重视实用性,让大家学完本套教程以后,基本的界面程序都能很容易编写出来。VC+简介VC+全
2、称是 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 占用的系统资源比较少,打开工程、编译运行都比较快,所以赢得很多软件开发者的青睐。但因为它先于 C
4、+标准推出,所以对 C+标准的支持不太好。举个例子:for(int i=0;i5;i+)ai=i;for 语句中声明的变量 i,对于 VC+6.0 来说,出了 for 循环仍能使用。但很显然这与 C+标准对于变量生存期的规定不符合。随着 VC+版本的更新,对 C+标准的支持越来越好,对各种技术的支持也越来越完善。但同时新版本所需的资源也越来越多,对处理器和内存的要求越来越高。到 VS2010,光安装文件就 2G 多,安装后的文件占 3G 多空间,其运行也经常受处理器和内存等性能的限制。但鸡啄米还是推荐大家使用VS2010,毕竟它是最新版本,类库和开发技术都是最完善的,本教程也将使用VS2010
5、 为大家做例程的演示。当然如果系统配置确实比较低,可以选择 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 应用程序,同样也能够进行 WindowsSDK 编程,但是那样的话就舍弃了 VC+的核心,放弃了 VC+最强大的部分。MFC也不是只能用于 VC+中,它同样也可以用在 Borland C+等编译器中,当然没有几个人这样做。本节旨在让大家对 VC+、VS2010 和 MFC 有基本的概念上的认识,后面鸡啄米会带大家进入 VS2010/MFC 的世界,让大家轻松的开发各种包含窗口、图
7、形等的可视化程序。V S2 010/M FC 编程 入门 之一(V S20 10 与 M SD N 安装 过程 图解)上一讲中鸡啄米对 VC+和 MFC 做了一些简单介绍。在本套教程中鸡啄米将使用VS2010 为大家讲解如何使用 VC+和 MFC 进行编程,所以首先要安装 VS2010。一.下载 VS2010首先我们需要下载 VS2010,大家可以在网上下载 VS2010 破解正式版,建议选择英文版,养成使用英文工具的习惯。鸡啄米使用 VS2010 旗舰试用版 VS2010UltimTrial.iso 为例介绍安装过程,旗舰试用版官方下载地址为:http:/VS2010下载后进行安装。安装方法
8、与一般的 iso 文件一样,可以使用虚拟光驱软件 Daemon Tools 安装,也可以将其解压后点击 setup.exe 进行安装。鸡啄米为了让大家更直观的看到安装过程,我将在自己机子上再重新安装一次,并截图为大家讲解。这里使用 Daemon Tools 安装 VS2010。首先打开 Daemon Tools,屏幕右下角会出现托盘图标,在图标上点右键,会弹出菜单,再把鼠标移到菜单项“虚拟设备”上,然后再移到子菜单项“设备 0:L:无媒体”上,最后点击下一级子菜单项“装载映像”,弹出对话框选择 VS2010UltimTrial.iso 文件。这样虚拟光驱就会打开此 iso 文件,弹出自动安装的
9、提示,选择“运行 autorun.exe”就可以了,如果没有弹出提示就通过资源管理器进入虚拟光驱,用 setup.exe 安装。接着会弹出下面的对话框:当然选择“Install Microsoft Visual Studio 2010”进入下一步,加载安装组件后如下显示:点“Next”后:选择“I have read and accept the license terms”后点“Next”弹出对话框:此处是让我们选择要安装的功能,有两种:Full(完全)和 Custom(自定义)。Full 选项表示安装所有编程语言和工具,Custom 选择表示可以自定义要安装的编程语言和工具。右侧可以更改安
10、装路径,鸡啄米建议不要安装 到C 盘,因为它占用的空间比较大。鸡啄米安装到了 D 盘,使用 Full 完全安装。如果选择 Custom 安装,点“Next”则出现如下画面:大家可以根据自己的需要取消某些语言或工具的安装,比如不想安装 Visual C#,取消选择它就可以了。如果觉得以后都有可能会用到,那就像鸡啄米一样选择完全安装吧。Full 或 Custom 方式和安装路径设置好后,点“Install”进行安装:可能正式版的安装文件在安装过程中会有重启过程。鸡啄米使用的试用版中间并没有重启。安装完成:如果要继续安装 MSDN,先不要卸载虚拟光驱映像。三.安装 MSDN我们使用 VS2010 进
11、行软件开发同样离不开帮助文档,即MSDN。在本地安装 MSDN 的方法如下:在开始菜单的“所有程序”-“Microsoft Visual Studio2010”-“Visual Studio Tools”下选择“Manage Help Settings-ENU”:弹出对话框:可以将帮助库存在默认路径,也可以修改存放路径。鸡啄米使用默认路径,点“OK”出现:选择“Install Content From Disk”后弹出对话框选择帮助所在文件,这时需要在加载了 VS2010 的虚拟光驱中找,选择图中所示路径:点 OK 后出现如下对话框,可以点“Add”选择要添加的帮助库,全部添加。点“Updat
12、e”进行安装,等待其完成就可以了。使用 MSDN 时点击开始菜单的“所有程序”-“MicrosoftVisual Studio 2010”-“Microsoft Visual Studio 2010 Documentation”即可。到此 VS2010 和 MSDN 的安装过程就结束了。以后就可以正式使用 VS2010 进行软件开发了。至于 VS2010 的使用方法在鸡啄米的 C+编程入门系列中已经介绍过,大家可以看看。V S2 010/M FC 编程 入门 之二(利用 M FC 向导 生成 单文档 应用 程序框 架)上一讲中讲了 VS2010 和 MSDN 如何安装,相信大家都已经安装好了。
13、这一讲给大家一个简单的例子,演示如何生成单文档应用程序框架。解决方案与工程鸡啄米在 VS2010 的使用介绍中已经讲了解决方案与工程的概念,这里再重提一下。每个应用程序都作为一个工程来处理,它包含了头文件、源文件和资源文件等,这些文件通过工程集中管理。在 VS2010 中,工程都是在解决方案管理之下的。一个解决方案可以管理多个工程,可以把解决方案理解为多个有关系或者没有关系的工程的集合。VS2010 提供了一个 Solution Explorer 解决方案浏览器视图,可以显示当前解决方案的内容,当新建一个工程时可以选择新建一个解决方案还是加入当前解决方案。下图左侧面板中正在显示的视图就是 So
14、lution Explorer,视图中有一个解决方案-HelloWorld,此解决方案下有一个同名的工程-HelloWorld。在应用程序向导生成应用程序后,VS2010 会在用户设置的路径下,以解决方案名为名称建立一个目录,里面存放自动生成的文件。使用 VS2010 应用程序向导生成单文档应用程序框架鸡啄米这里简略演示下怎样生成单文档应用程序框架,让大家先有个直观的了解,有不理解的地方可以留着以后回来再看。下面按照操作步骤一步步讲解:1.点菜单栏 File-New-Project,弹出 New Project 对话框,我们可以选择工程类型。如果安装完 VS2010 以后第一启动时已经设置为
15、VC+,则 InstalledTemplates-Visual C+项会默认展开,而如果没有设置 VC+,则可以展开到Installed Templates-Other Languages-Visual C+项。因为我们要生成的 是MFC 程序,所以在“Visual C+”下选择“MFC”,对话框中间区域会出现三个选项:MFC ActiveX Control、MFC Application 和 MFC DLL。MFC ActiveX Control用来生成 MFC ActiveX 控件程序。MFC Application 用来生成 MFC 应用程序。MFCDLL 用来生成 MFC 动态链接库程
16、序。当然我们要选择 MFC Application。在对话框下部有 Name、Location 和 Solution name 三个设置项。意义如下:Name-工程名,Location-解决方案路径,Solution name-解决方案名称。这里 Name 我们设为“HelloWorld”,Location 设置为“桌面”的路径,Solution name 默认和 Name 一样,当然可以修改为其他名字,这里我们不作修改,也使用“HelloWorld”。点“OK”按钮。2.这时会弹出“MFC Application Wizard”对话框,上部写有“Welcome to the MFC Appl
17、ication Wizard”,下面显示了当前工程的默认设置。第一条“Tabbed multiple document interface(MDI)”是说此工程是多文档应用程序。如果这时直接点下面的“Finish”按钮,可生成具有上面列出设置的多文档程序。但我们此例是要建立单文档应用程序,所以点“Next”按钮再继续设置吧。3.接下来弹出的对话框上部写有“Application Type”,当然是让选择应用程序类型,我们看到有四种类型:Single document(单文档)、Multipledocuments(多文档)、Dialog based(基于对话框)和 Multiple top-le
18、veldocuments。我们选择 Single document 类型,以生成一个单文档应用程序框架。单文档应用程序运行时是一个单窗口界面。此对话框的“Resource language”还提供语言的选择,这里默认选择英语。“Project style”可选择工程风格,我们选择默认的“Visual Studio”风格。“Use of MFC”有两个选项:Use MFC in a shared DLL(动态链接库方式使用MFC)和 Use MFC in a static library(静态库方式使用 MFC)。选择 Use MFCin a shared DLL 时 MFC 的类会以动态链接库
19、的方式访问,所以我们的应用程序本身就会小些,但是发布应用程序时必须同时添加必要的动态链接库,以便在没有安装 VS2010 的机子上能够正常运行程序。选择 Use MFC in a static library时 MFC 的类会编译到可执行文件中,所以应用程序的可执行文件要比上种方式大,但可以单独发布,不需另加包含 MFC 类的库。这里我们使用默认的 Use MFCin a shared DLL。点“Next”按钮。4.此时弹出上部写有“Compound Document Support”的对话框,可以通过它向应用程序加入 OLE 支持,指定 OLE 选项的复合文档类型。本例不需要OLE 特性,
20、使用默认值“None”。点“Next”按钮。5.弹出的新对话框上部写有“Document Template Properties”。“File extension”可以设置程序能处理的文件的扩展名。对话框其他选项还可以更改程序窗口的标题。我们都使用默认设置,点“Next”按钮。6.此时弹出的对话框主题是“Database Support”。用于设置数据库选项。此向导可以生成数据库应用程序需要的代码。它有四个选项:None:忽略所有的数据库支持;Header files only:只包含定义了数据库类的头文件,但不生成对应特定表的数据库类或视图类;Database view without fi
21、le support:创建对应指定表的一个数据库类和一个视图类,不附加标准文件支持;Database view with file support:创建对应指定表的一个数据库类和一个视图类,并附加标准文件支持。本例选择默认值“None”,不使用数据库特性。点“Next”按钮。7.这时弹出的对话框是关于“User Interface Features”,即用户界面特性。我们可以设置有无最大化按钮、最小化按钮、系统菜单和初始状态栏等。还可以选择使用菜单栏和工具栏生成简单的应用程序还是使用 ribbon。这里我们都选择默认设置。点“Next”进入下一步。8.此时弹出“高级特性”对话框。可以设置的高级
22、特性包括有无打印和打印预览等。在“Number of files on recent file list”项可以设置在程序界面的文件菜单下面最近打开文件的个数。我们仍使用默认值。点“Next”按钮。9.弹出“生成类”对话框。在对话框上部的“生成类”列表框内,列出了将要生成的 4 个类:一个视图类(CHelloWorldView)、一个应用类(CHelloWorldApp)、一个文档类(CHelloWorldDoc)和一个主框架窗口类(CMainFrame)。在对话框下面的几个编辑框中,可以修改默认的类名、类的头文件名和源文件名。对于视图类,还可以修改其基类名称,默认的基类是 CView,还有其
23、他几个基类可以选择。这里我们还是使用默认设置。点“Finish”按钮。应用程序向导最后为我们生成了应用程序框架,并在 SolutionExplorer 中自动打开了解决方案(见上面第一张图)。编译运行生成的程序点菜单中的 Build-Build HelloWorld 编译程序,然后点Debug-Start Without Debugging(快捷键 Ctrl+F5)运行程序,也可以直接 点Debug-Start Without Debugging,这时会弹出对话框提示是否编译,选择“Yes”,VS2010 将自动编译链接运行 HelloWorld 程序。结果页面如下所示:V S2 010/M
24、FC 编程 入门 之三(V S20 10 应用 程序 工程中 文件 的组成 结构)鸡啄米在上一讲中为大家演示了如何利用应用程序向导创建单文档应用程序框架。这一节将以上一讲中生成应用程序 HelloWorld 的文件结构为例,讲解 VS2010应用程序工程中文件的组成结构。用应用程序向导生成框架程序后,我们可以在之前设置的Location 下看到以解决方案名命名的文件夹,此文件夹中包含了几个文件和一个以工程名命名的子文件夹,这个子文件夹中又包含了若干个文件和一个 res文件夹,创建工程时的选项不同,工程文件夹下的文件可能也会有所不同。如果已经以 Debug 方式编译链接过程序,则会在解决方案文件
25、夹下和工程子文件夹下各有一个名为“Debug”的文件夹,而如果是 Release 方式编译则会有名为“Release”的文件夹。这两种编译方式将产生两种不同版本的可执行程序:Debug 版本和 Release 版本。Debug 版本的可执行文件中包含了用于调试的信息和代码,而 Release 版本则没有调试信息,不能进行调试,但可执行文件比较小。鸡啄米将所有文件分为 6 个部分:解决方案相关文件、工程相关文件、应用程序头文件和源文件、资源文件、预编译头文件和编译链接生成文件。1.解决方案相关文件解决方案相关文件包括解决方案文件夹下的.sdf 文件、.sln 文件、.suo 文件和 ipch 文
26、件夹。.sdf 文件和 ipch 目录一般占用空间比较大,几十兆甚至上百兆,与智能提示、错误提示、代码恢复和团队本地仓库等相关。如果你觉得不需要则可以设置不生成它们,方法是点击菜单栏 Tools-Options,弹出 Options 对话框,选择左侧面板中 Text Editor-C/C+-Advanced,右侧列表中第一项 DisableDatabase 由 False 改为 True 就可以了,最后关闭 VS2010 再删除.sdf 文件和 ipch目录以后就不会再产生了。但关闭此选项以后也会有很多不便,例如写程序时的智能提示没有了。.sln 文件和.suo 文件为 MFC 自动生成的解决
27、方案文件,它包含当前解决方案中的工程信息,存储解决方案的设置。2.工程相关文件工程相关文件包括工程文件夹下的.vcxproj 文件和.vcxproj.filters 文件。.vcxproj 文件是 MFC 生成的工程文件,它包含当前工程的设置和工程所包含的文件等信息。.vcxproj.filters 文件存放工程的虚拟目录信息,也就是在解决方案浏览器中的目录结构信息。3.应用程序头文件和源文件应用程序向导会根据应用程序的类型(单文档、多文档或基于对话框的程序)自动生成一些头文件和源文件,这些文件是工程的主体部分,用于实现主框架、文档、视图等。鸡啄米下面分别简单介绍下各个文件:HelloWorl
28、d.h:应用程序的主头文件。主要包含由 CWinAppEx 类派生的 CHelloWorldApp 类的声明,以及 CHelloWorldApp 类的全局对象 theApp的声明。HelloWorld.cpp:应用程序的主源文件。主要包含CHelloWorldApp 类的实现,CHelloWorldApp 类的全局对象 theApp 的定义等。MainFrm.h 和 MainFrm.cpp:通过这两个文件从 CFrameWndEx 类派生出 CMainFrame 类,用于创建主框架、菜单栏、工具栏和状态栏等。HelloWorldDoc.h 和 HelloWorldDoc.cpp:这两个文件从C
29、Document 类派生出文档类 CHelloWorldDoc,包含一些用来初始化文档、串行化(保存和装入)文档和调试的成员函数。HelloWorldView.h 和 HelloWorldView.cpp:它们从 CView 类派生出名为 CHelloWorldView 的视图类,用来显示和打印文档数据,包含了一些绘图和用于调试的成员函数。ClassView.h 和 ClassView.cpp:由 CDockablePane 类派生出CClassView 类,用于实现应用程序界面左侧面板上的 Class View。FileView.h 和 FileView.cpp:由 CDockablePan
30、e 类派生出CFileView 类,用于实现应用程序界面左侧面板上的 File View。OutputWnd.h 和 OutputWnd.cpp:由 CDockablePane 类派生出COutputWnd 类,用于实现应用程序界面下侧面板 Output。PropertiesWnd.h 和 PropertiesWnd.cpp:由 CDockablePane 类派生出 CPropertiesWnd 类,用于实现应用程序界面右侧面板 Properties。ViewTree.h 和 ViewTree.cpp:由 CTreeCtrl 类派生出 CViewTree类,用于实现出现在 ClassView
31、和 FileView 等中的树视图。4.资源文件一般我们使用 MFC 生成窗口程序都会有对话框、图标、菜单等资源,应用程序向导会生成资源相关文件:res 目录、HelloWorld.rc 文件和Resource.h 文件。res 目录:工程文件夹下的 res 目录中含有应用程序默认图标、工具栏使用图标等图标文件。HelloWorld.rc:包含默认菜单定义、字符串表和加速键表,指定了默认的 About 对话框和应用程序默认图标文件等。Resource.h:含有各种资源的 ID 定义。5.预编译头文件几乎所有的 MFC 程序的文件都要包含 afxwin.h 等文件,如果每次都编译一次则会大大减慢
32、编译速度。所以把常用的 MFC 头文件都放到了 stdafx.h文件中,然后由 stdafx.cpp 包含 stdafx.h 文件,编译器对 stdafx.cpp 只编译一次,并生成编译之后的预编译头 HelloWorld.pch,大大提高了编译效率。6.编译链接生成文件如果是 Debug 方式编译,则会在解决方案文件夹和工程文件夹下都生成 Debug 子文件夹,而如果是 Release 方式编译则生成 Release 子文件夹。工程文件夹下的 Debug 或 Release 子文件夹中包含了编译链接时产生的中间文件,解决方案文件夹下的 Debug 或 Release 子文件夹中主要包含有应用
33、程序的可执行文件。V S2 010/M FC 编程 入门 之四(M FC 应用 程序 框架分 析)上一讲鸡啄米讲的是 VS2010 应用程序工程中文件的组成结构,可能大家对工程的运行原理还是很模糊,理不出头绪,毕竟跟 C+编程入门系列中的例程差别太大。这一节鸡啄米就为大家分析下 MFC 应用程序框架的运行流程。一.SDK 应用程序与 MFC 应用程序运行过程的对比程序运行都要有入口函数,在之前的 C+教程中都是 main 函数,而 Windows 应用程序的入口函数是 WinMain 函数,MFC 程序也是从 WinMain 函数开始的。下面鸡啄米就给出用 Windows SDK 写的“Hel
34、loWorld”程序,与应用程序框架进行对比,这样能更好的了解框架是怎样运行的。Windows SDK 开发程序就是不使用 MFC 类库,直接用 Windows API 函数进行软件开发。鸡啄米不是要讲解 SDK 开发,只是为了对比而简单介绍,至于 SDK 开发可以在大家学完 MFC 以后选择是否要研究,一般来说有简单了解就可以了。SDK 应用程序首先,给出 Windows SDK 应用程序“HelloWorld”的源码:C+代码include int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTRszCmdLin
35、e,int iCmdShow)const static TCHAR appName=TEXT(Hello world);WNDCLASSEX myWin;myWin.cbSize=sizeof(myWin);myWin.style=CS_HREDRAW|CS_VREDRAW;myWin.lpfnWndProc=myWndProc;myWin.cbClsExtra=0;myWin.cbWndExtra=0;myWin.hInstance=hInstance;myWin.hIcon=0;myWin.hIconSm=0;myWin.hCursor=0;myWin.hbrBackground=(HBR
36、USH)(COLOR_WINDOW+1);myWin.lpszMenuName=0;myWin.lpszClassName=appName;/Registerif(!RegisterClassEx(&myWin)return 0;const HWND hWindow=CreateWindow(appName,appName,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,0,0,hInstance,0);ShowWindow(hWindow,iCmdShow);UpdateWindow(hW
37、indow);MSG msg;while(GetMessage(&msg,0,0,0)TranslateMessage(&msg);DispatchMessage(&msg);return(int)msg.wParam;LRESULT CALLBACK myWndProc(HWND hWindow,UINT msg,WPARAM wParam,LPARAMlParam)if(msg=WM_PAINT)PAINTSTRUCT ps;const HDC hDC=BeginPaint(hWindow,&ps);RECT rect;GetClientRect(hWindow,&rect);DrawTe
38、xt(hDC,TEXT(HELLO WORLD),-1,&rect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);EndPaint(hWindow,&ps);return 0;else if(msg=WM_DESTROY)PostQuitMessage(0);return 0;return DefWindowProc(hWindow,msg,wParam,lParam);上面的程序运行的流程是:进入 WinMain 函数-初始化WNDCLASSEX,调用 RegisterClassEx 函数注册窗口类-调用 ShowWindow 和UpdateWindow 函数显示并
39、更新窗口-进入消息循环。关于消息循环再简单说下,Windows 应用程序是消息驱动的,系统或用户让应用程序进行某项操作或完成某个任务时会发送消息,进入程序的消息队列,然后消息循环会将消息队列中的消息取出,交予相应的窗口过程处理,此程序的窗口过程函数就是 myWndProc 函数,窗口过程函数处理完消息就完成了某项操作或任务。本例是要显示“HELLOWORLD”字符串,UpdateWindow 函数会发送 WM_PAINT 消息,但是此消息不经过消息队列而是直接送到窗口过程处理,在窗口过程函数中最终绘制了“HELLOWORLD”字符串。MFC 应用程序下面是 MFC 应用程序的运行流程,通过 M
40、FC 库中代码进行分析:首先在 HelloWorld.cp p 中定义全局对象 theApp:CHelloWorldApptheApp;。调用 CWinApp 和 CHelloWorldApp 的构造函数后,进入 WinMain 函数(位于 appmodul.cpp 中)。C+代码extern C int WINAPI_tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,_In_ LPTSTR lpCmdLine,int nCmdShow)#pragma warning(suppress:4985)/call shared/exported
41、 WinMainreturn AfxWinMain(hInstance,hPrevInstance,lpCmdLine,nCmdShow);在 TCHAR.h 中,有此定义:#define _tWinMain WinMain,所以这里的_tWinMain 就是 WinMain 函数。它调用了 AfxWinMain 函数(位于WinMain.cpp 中)。C+代码int AFXAPI AfxWinMain(HINSTANCE hInstance,HINSTANCEhPrevInstance,LPTSTR lpCmdLine,int nCmdShow).略/App global initializ
42、ations(rare)if(pApp!=NULL&!pApp-InitApplication()goto InitFailure;if(!pThread-InitInstance().略/Run 函数位于 THRDCORE.cpp 中,由此函数进入消息循环nReturnCode=pThread-Run();.略return nReturnCode;上面 InitInstance 函数的代码如下:C+代码BOOL CTestApp:InitInstance().略CSingleDocTemplate*pDocTemplate;pDocTemplate=new CSingleDocTemplat
43、e(IDR_MAINFRAME,RUNTIME_CLASS(CTestDoc),RUNTIME_CLASS(CMainFrame),/main SDI frame windowRUNTIME_CLASS(CTestView);if(!pDocTemplate)return FALSE;AddDocTemplate(pDocTemplate);/Parse command line for standard shell commands,DDE,fileopenCCommandLineInfo cmdInfo;ParseCommandLine(cmdInfo);/ProcessShellComm
44、and 位于 AppUI2.cpp 中,注册并创建窗口if(!ProcessShellCommand(cmdInfo)return FALSE;m_pMainWnd-ShowWindow(SW_SHOW);m_pMainWnd-UpdateWindow();return TRUE;InitInstance 中的 ProcessShellCommand 函数又调用了CMainFrame 的 LoadFrame 函数注册并创建了窗口,执行完 ProcessShellComman d函数以后,调用了 m_pMainWnd 的 ShowWindow 和 UpdateWindow 函数显示并更新框架窗口
45、。这些是不是与上面的 SDK 程序十分类似?接下来该是消息循环了,上面的 AfxWinMain 函数中调用了pThread 的 Run 函数(位于 THRDCORE.cpp 中),在 Run 中包含了消息循环。Run函数的代码如下:C+代码int CWinThread:Run().略/phase2:pump messages while availabledo/pump message,but quit onWM_QUITif(!PumpMessage()returnExitInstance();/reset no idle state after pumpingnormal messagei
46、f(IsIdleMessage(&m_msgCur)bIdle=TRUE;lIdleCount=0;while(:PeekMessage(&m_msgCur,NULL,NULL,NULL,PM_NOREMOVE);.略BOOL CWinThread:PumpMessage()return AfxInternalPumpMessage();BOOL AFXAPI AfxInternalPumpMessage()_AFX_THREAD_STATE*pState=AfxGetThreadState();if(!:GetMessage(&(pState-m_msgCur),NULL,NULL,NULL
47、).略.略if(pState-m_msgCur.message!=WM_KICKIDLE&!AfxPreTranslateMessage(&(pState-m_msgCur):TranslateMessage(&(pState-m_msgCur);:DispatchMessage(&(pState-m_msgCur);return TRUE;我们看到 PumpMessage 中通过调用 GetMessage、TranslateMessage、DispatchMessage 等建立了消息循环并投递消息。窗口过程函数 AfxWinProc 形式如下:C+代码LRESULT CALLBACK Afx
48、WndProc(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAMlParam)CWnd*pWnd=CWnd:FromHandlePermanent(hWnd);ReturnAfxCallWndProc(pWnd,hWnd,nMsg,wParam,lParam);两者运行过程对比到此,通过对比可以发现,MFC 应用程序的运行流程与 SDK 程序是类似的,都是先进行一些初始化过程,再注册并创建窗口,然后显示、更新窗口,最后进入消息循环,消息都由窗口过程函数处理。现在大家是不是觉得有些头绪了?在运行流程上有基本的掌握即可。二.MFC 应用程序框架主要类之间的关系在第二
49、讲中,给大家演示了如何利用应用程序向导生成单文档应用程序框架,可以看到程序的基本框架和必要的代码都自动生成了,上一讲又讲解了文件组成结构,实际上在前面自动生成的框架中比较重要的类包括以下几个:CHelloWorldApp、CMainFrame、CHelloWorldDoc 和 CHelloWorldView,至于其他的类比如 CClassView、CFileView 等都是在框架窗口(CMainFrame)上创建的面板等,不是必要的。鸡啄米就四个主要类的关系简单讲下,CHelloWorldApp 类处理消息,将收到的消息分发给相应的对象。CMainFrame 是视图 CHelloWorldVi
50、ew 的父窗口,视图 CHelloWorldView 就显示在 CMainFrame 的客户区中。视图类CHelloWorldView 用来显示文档类 CHelloWorldDoc 中的数据,并根据对视图类的操作修改文档类的数据。一个视图类只能跟一个文档类相联系,而一个文档类可以跟多个视图类相联系。关于视图类和文档类的关系后面会详细讲解。V S2 010/M FC 编程 入门 之五(M FC 消息 映射 机制概 述)上一讲鸡啄米为大家简单分析了 MFC 应用程序框架,这一讲是关于 MFC 消息映射机制的内容。前面已经说过,Windows 应用程序是消息驱动的。在 MFC 软件开发中,界面操作或