《用Eclipse + CDT + MinGW做Windows编程.pdf》由会员分享,可在线阅读,更多相关《用Eclipse + CDT + MinGW做Windows编程.pdf(23页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、用用 Eclipse+CDT+MinGW 做做Windows 编程编程Inshion mailto:1/23内容目录内容目录前言前言.3第一部分 开发环境配置第一部分 开发环境配置.3第二部分 第二部分 Windows 编程、面向对象程序设计编程、面向对象程序设计.62.1 Windows 编程回顾.62.2 图解程序结构.72.3 用对象封装WindowsAPI.9第三部分 一个第三部分 一个Demo 程序及相关说明程序及相关说明.123.2 源代码说明.13第四部分 将可重用的部分做成静态库第四部分 将可重用的部分做成静态库.174.2 静态库项目的建立.174.3 静态库项目的调用.18
2、1:头文件.182:引用库和参数配置.194.3 其它可能遇到的问题.202/23前言前言以前看到一本书,叫Visual C+角色扮演游戏程序设计,是一个叫坂本千寻的日本人所著。就我的感觉而言,这本书的内容还是挺丰富,不过每一方面的内容都不是太细,所以想要全靠它就能从无知到入门,是很困难的。但是该书最大的好处就是提供了一系列的Demo,分别演示了书中提到的某一方面。(这些和Eclipse CDT 有什么关系吗?=0=|别急,哈哈,就快有关系了_/)书的前两章主要是一些概要性的叙述,基本不涉及具体的技术。从第三章“Windows 程序设计”开始,就进入具体技术环节。正好这两天大致研究了一下 Ec
3、ilpse+CDT 做C+程序(这不就有关系了吗,哈哈),而且我认为这第三章的内容对 Windows 程序设计和面向对象编程思想的理解很有帮助,于是就用 Eclipse 的+CDT 从这一部分开始,对书中的内容进行了练习。具体地说,就是在Eclipse 上搭建上C+的环境,再做出同书中例子程序相似的Demo。这篇文章主要就是写来总结一下整个过程中遭遇到的各种问题,同时也复习一下关于Windows 和面向对象程序开发的一些内容。3/23第一部分 开发环境配置第一部分 开发环境配置Eclipse+CDT我用的是从Eclipse.org 上下载的 Eclipse IDE for C/C+Develo
4、pers。打开一看,是Eclipse3.4.1+CDT 5.0.1.200809120802。MinGW我用的是MinGW-3.1.0-1。安装的时候,先装好MinGW,装在C:MinGW 下,然后运行Eclipse IDE,这基本上就可以了。需要一提的是,我下到的这个 MinGW 是一个完全本地安装的版本,如果例用在线安装那种方式的安装,建议在选择安装组件的时候,尽量都选上建议在选择安装组件的时候,尽量都选上,否则在后续使用时可能会造成相当的麻烦。测试一下是否成功:首先在Eclipse 中新建一个项目。选择File-New-C+Project-Executable-Hello World C
5、+Project。建完以后,会自动生成一个CPP文件,打开看看,就是一个简单的Main 函数。先Build 再Run,一般来说是正常通过的。然后再建一个Makefile 的项目看看。选择File-New-C+Project-Makefile project-Hello World C+Project。此时向导右侧会出现一个列表,有-Other Toolchain-和MinGW GCC,此时一定要选择此时一定要选择MinGW GCC。然后输入名称建项目,建完后Build,提示出错提示出错(Cannot run program make:Launching failed)。于是去MinGW 的安装
6、目录C:MinGWbin 下将将mingw32-make.exe 复制成复制成 make.exe即可即可。再Build、运行,一切正常,至此,环境配置完成。4/23在下一部分中,我将讲述Windows 程序设计与面向对象程序设计的思想,在该思想的指导下,再进行程序开发。5/23第二部分 第二部分 Windows编程、面向对象程序设计编程、面向对象程序设计2.1 Windows 编程回顾编程回顾提到Windows 编程,简单地说,就是调用WIndows API 做 Windows 应用程序。比如画个窗口,写个菜单,放个按钮,响应响应鼠标之类的。基本上所有的相关入门教程,都会用以下这样一个小例子,
7、来演示一个最简单的 Windows 应用:/-Start-#include./回调函数LRESULT WndProc()/switch msg.WM_PAINT:OnPaint();.void OnPaint()/draw/入口int WinMain()/1:注册窗口类,并将该窗口的回调函数调为:注册窗口类,并将该窗口的回调函数调为WndProc/2:建立并显示窗口:建立并显示窗口/3:进入消息循环:进入消息循环/-End-从上面程序可以看出,正常的Windows 程序编写,都会有上述的1、2、3步。这样一来,6/23运行时一个Win 窗体就会诞生,并且源源不断地接收系统和用户发给它的各种消息
8、,比如单击、移动、关闭等。然后在此基础上,我们就可以编写自己的功能,比如每当单击窗口的某一处就显示一个图片、每当用户点关闭按钮,就弹出一个提示框,等等诸如此类的操作。这些功能都需要在WndProc 的 switch 语句中添加。由此就产生了一个问题。“我是不是需要经常改动WndProc 或者它所调用的函数(如OnPaint)的内容?”OK,一般说来,是这样的。所以这会给开发造成很多麻烦,比如需要经常修改同一段代码,又比如每建立一个应用程序,都要重复写以上的那个结构等等等等。于是我们就郁闷了,开始考虑怎么才能来点儿一劳永逸的办法,使得上述那样 3步可以固化下来,以后再要开发,只需要写功能,不需要
9、对已经写好的东西再复制或者修改了。幸运的是,面向对象的开发方法给了我们很好的解决方案。2.2图解程序结构图解程序结构结过分析,我们发现Window 应用程序,一般都有着如下的结构。即入口WinMain 通过一个全局的Application*application 来调用Application 的InitInstance()方法,而Application:InitInstance()中又调用 Window:Create()方法。这样一来,Window 被创建,而系统、用户消息,如WM_PAINT 之类的就可以传由Window 的相应处理函数来处理。这样一来,程序底层就完成了,简单地说,这是一个没
10、有任何功能的,但是可以接受各种消息的Windows 应用。当我们想添加自己的功能时,只需要按照下图所示,分别继承 Application 和 Window类。并在在WinMain 执行之前让全局的执行之前让全局的application 指向指向MyApp的实例的实例,这样一来,新程序中所有的消息就会转到我们自己的MyWin 类中来处理,我们就可以随心所欲地添加自己的功能。7/23到此,可能有人会有疑问:“在WinMain 执行之前让全局的application 指向MyApp 的实例”?WinMain 不是程序入口吗,怎么能在它执行之前还能做别的操作?不是程序入口吗,怎么能在它执行之前还能做别
11、的操作?这个问题甚至不需要回答,如果有此疑问的,请运行下面这样一段小程序下面这样一段小程序,看看输出就明白了,为什么在WinMain 之前还可以做很多很多操作:Code 001/-Start-#include using namespace std;int main()cout 我是 main()中第一行,我总是会第一个输出的吧!endl;/prints!Hello World!return 0;class Apublic:A()cout哈哈,那可不一定,我就会比main()早执行哦init();app-run()9/23/-OK,这个结构是什么意思?简单地说,就是把应用程度做成一个类,窗口做
12、成一个类。程序入口调用程序的init()方法,该方法会调用窗口的create()方法,最后调用程序的 run()方法完成程序的加载。这样做的好处是什么?回答是:可以完全不改动这些代码,只需要添加新的代码,并且新的代码只需要关注自己新的功能,不需要知道消息从哪来,往哪去就可以开发出我们自己的应用程序!为什么可以这样?举例说明一下。(注意那个App 的指针 app,以及App 构造函数中的app=this;,再看看那几个virtual 函数。)比如我们要建立自己的应用,可以写一个如下的类:/-MyApp theApp;MyApp:public AppWindow win;init()win.cre
13、ate();MainWin=&win;/-/-MyWin:public WindowOnPaint();OnClose();./-只要这样,我们就可以在MyWin 的OnXXXX()方法里实现我们自己的功能,而前面编好的那几个类,可以不做任何改动,就可以支撑起整个程序的过程调用,我们甚至不需要上10/23面那些源代码了,只需要将编译好的库和头文件引进来,就可以在其基础上进行扩展。整个调用过程是,App 的实例化由MyApp theApp;完成,由于 App的构造函数中有app=this;,所以此时 app 指向的是 MyApp 的实例。当程序接收到消息时,会通过WndProc 找到对应的处理函
14、数(比如WM_PAINT 对应到 OnPaint()方法),此时会调用MainWin-OnPaint()。而由于 MainWin 的实例是MyApp:init()中生成的,是MyWin 的实例,而MyWin 中将 virtual的 OnPaint()进行了重载,所以该调用会调到MyWin:OnPaint()方法。总结起来,这实际上完成了一个将将 WindowsAPI 的过程封装成的过程封装成C+类类的过程,用类和对象架起了用户调用与WindowsAPI 之间的一座桥梁。这里可以提一句关于MFC的话题,MFC 所做的事情,就是这样一个将所做的事情,就是这样一个将 WindowsAPI的过程封装成
15、的过程封装成 C+类的过程类的过程,当然,它的结构更为严谨而复杂,考虑的事情也更多,远不是一两句话能说完,不过其思想与程序封装完的入口,与上述过程如出一辙。至此,我们就清楚了如何用面向对象思想解决 Windows 程序的问题。在下一部分中,我将完整地给出一个将完整地给出一个 C+程序(程序(Eclipse+CDT),并且总结一些Eclipse 中编译运行之可能遇到的问题,用以完成这部分所描述的内容。11/23第三部分 一个第三部分 一个 Demo 程序及相关说明程序及相关说明3.1 在在eclipse 中导入并运行一个中导入并运行一个 C+项目项目点此处可以下载本文中用到的C+项目(Eclip
16、se+CDT 项目,环境按第一部分的说明配置),下载后解压。然后在Eclipse 中使用 File-Import-Genaral:Existing Project into Workspace 向导即可把下载的项目导入到开发环境中。便会看到如下图的项目:如果如果Build 成功成功,Run 起来以后,可以看到如下的运行结果:同时控制台给出以下输出:Main Program Started!Application:SetWinMainArgs(.)MyApp:InitInstance()-startWindow:Create(.)start12/23Application:RegisterWnd
17、Class(.)startApplication:RegisterWndClass(.)endWindow:Create(.)endMyApp:InitInstance()-endApplication:Run()但是需要注意的是,如果是直接新建一个项目,再编写如此的程序代码,调用如果是直接新建一个项目,再编写如此的程序代码,调用WindowsAPI,一般情况下直接编是编不通的,会提示某种错误,一般情况下直接编是编不通的,会提示某种错误比如:undefined reference to TextOutA20或者是:undefined reference to SetBkColor8等因此要对项
18、目加上一个参数设置。因此要对项目加上一个参数设置。具体的设置项目如下:在项目上点右键,选择“属性”,就会弹出 Eclipse 的项目设置对话框,在按图所示的地方添加-mwindows 参数即可(C/C+Build-Settings-MinGW C+Linker-Expert settings:)。注意,这些选项页中有很多相似的页面,看清图示的设置框究竟是哪一个选项页中有很多相似的页面,看清图示的设置框究竟是哪一个(MinGW C+Linker),不要加错地方了),不要加错地方了(=0=|)。顺便提一句,随着我们对项目的扩展,可能有越来越多的项目需求,比如引用静态库比如引用静态库、引用引用DLL
19、、使用、使用 rc 资源等,这些要求都涉及到对项目属性中某些参数的修改资源等,这些要求都涉及到对项目属性中某些参数的修改。本部分中只涉及-mwindows 参数,其它的参数会在后续的部分中分别介绍。OK,如果项目运行成功,我们就来分析一下这个项目的结构,看是否和第一部分描述的是同样的组织方式。3.2 源代码说明源代码说明13/23回顾一下第一部分中提到的Windows 应用程序的运行示意图:对照本文中给出的项目,可以看出 Main.cpp 中就是程序的入口 WinMain()函数;Application 类(包括.h 与.cpp两部分)就是图示的Application;Window类(包括.h
20、 与.cpp 两部分)就是图示的Window 部分;而application 变量(在 Application.cpp 中声明)就是图中左上角那全局变量。也就是说,本项目中的Application、Window两个类再加上一个WinMain()函数就完成了一个Windows 程序需要的基本框架。这三个类写定以后,就不需要再作改变(架构意义上而言)!而我们的后续开发扩展功能的工作,就只需要进行一些简单的添加就能完成就只需要进行一些简单的添加就能完成(下面马上讲到的(下面马上讲到的 MyWin 和和MyApp两个类的作用)两个类的作用),下面就是扩展部分的说明。还是先看看第一部分中提到的扩展程序示
21、意图:14/23MyApp 和MyWin 两个类,就是我们自己扩展出来的。实现上图中My Program 的功能。可以看到,我们的子类MyWin 的OnPaint()方法在运行过程中已经取代了基类Window 的OnPaint()方法,替我们输出了一个文本。总结一下,整个这个例子想要说明的一个问题就是:如果我们的底层结构(Application、Window两个类)写得足够好了,我们以后的开发只需要做MyWin 和MyApp两个类,在其中添加我们的功能即可,这种添加只需要很少的代码量,如本例中的这两个扩展类其实只有如下的内容,并且结构很清晰。(MyApp 和 MyWin 类)class MyA
22、ppnamespace inshion class MyApp:public inshion:Application public:MyApp()virtual MyApp()bool InitInstance()if(!MainWin.Create(this,Inshion-Test-001,0,0)return FALSE;MainWindow=&MainWin;return TRUE;protected:MyWin MainWin;MyApp theApp;class MyWinnamespace inshion class MyWin:public inshion:Window15/2
23、3public:MyWin()virtual MyWin()LRESULT WindowProc(UINT uMsg,WPARAM wParam,LPARAM lParam)switch(uMsg)case WM_PAINT:OnPaint();break;default:return Window:WindowProc(uMsg,wParam,lParam);return 0L;void OnPaint()PAINTSTRUCT ps;HDC hdc;hdc=BeginPaint(hWnd,&ps);PrintText(Hello,Im Inshion);EndPaint(hWnd,&ps)
24、;另外再提一下,我们可以试着把MyApp.h 中的成员变量定义MyWin MainWin;改回基类Window MainWin;此时的运行结果就是弹出一个基类的 Window,而与MyWin 无关(可以把MyWin 相关的代码删掉,依然不影响运行)。这一方面说明,如果我们的很多需求是大量重复的,就完16/23全可以在基类里做好,扩展时都不用写 MyWin 这样的窗口类;另一方面说明,即使我们要自己做扩展,也是非常方便地添加一个窗口类就可以。下一部分将介绍如何把基类们封装成静态库项目静态库项目,以便更方便地复用。附:本文中的源代码项目下载(MyMain_Inshion_Exa001.rar)17
25、/23第四部分 将可重用的部分做成静态库第四部分 将可重用的部分做成静态库4.1 导入示例项目导入示例项目点此处可以下载本文中用到的两个 C+项目(Eclipse+CDT 项目,环境按第一部分的说明配置),下载后解压。然后在Eclipse 中使用 File-Import-Genaral:Existing Project into Workspace 向导即可把下载的项目导入到开发环境中。便会看到如下图的项目:如果如果Build 成功成功,Run 起来以后,可以看到如下的运行结果:这个例子实际上和上一部分中的例子效果是一样的。不同的是,本例中使用了静态库的方式来完成,这样更可以看出程序在扩展意义
26、上的实践。那么如何建立一个静态库(那么如何建立一个静态库(static library)?又如何在另一个项目中引用这个库?)?又如何在另一个项目中引用这个库?下面两个小节就是分别回答这两个问题的。18/234.2 静态库项目的建立静态库项目的建立静态库项目的建立在CDT 中是非常方便的。用新建向导中的 New-C+Project-Static Library-Empty Project 即可建立成功。然后可以在该项目中进行代码的编写。如果编译成功,可以看到项目结构如下所示:注意那个Archives 里面生成的一个里面生成的一个*.a 文件,这就是代码编译生成的静态库文件,这就是代码编译生成的静
27、态库。4.3 静态库项目的调用静态库项目的调用下面就来新建一个普通C+项目,来引用并调用上一小节库中的代码。新建的过程也很简单,就用新建向导中的New-C+Project-Executable-Empty Project 即可。建完以后,来添加对4.2 中所建立的静态库的引用。1:头文件:头文件因为我们要对静态库中的类进行调用并扩展,所以一般需要引用静态库项目中的一个对外公布的头文件(如本例中的InshionLib.h)。19/23具体做法如上图所示,在/C/C+Build-Settings 中的GCC C+Compiler 的Directories中把需要引用的静态库的Include pat
28、hs 添加进来。这样做的目的是为了让为了让Inshion_Exa002_Caller 项目(下简称项目(下简称 Caller 项目)中的项目)中的#include InshionLib.h能正确通过能正确通过。2:引用库和参数配置:引用库和参数配置当然,只引入头文件是远远不够的。以 Caller 项目为例,如果只是添加了头文件目录,然后就编译那几个源码的话,一般会出现如下的错误:undefined reference to WinMain16undefined reference to TextOutA20undefined reference to SetBkColor8等等等等所以我们还需
29、要把需要把 Lib 项目生成的库引进来,同时设置项目生成的库引进来,同时设置 WindowsAPI调用需要添加的配调用需要添加的配置参数置参数。具体作法如下图所示:20/23具体地说就是在在MinGW C+Linker 的的 Miscellaneous 中的中的Other objects 下,添加前文下,添加前文提到的静态库编译生成的提到的静态库编译生成的*.a 库文件库文件。然后设置-lmingw32 和和-mwindows 参数,分别参照以下两图进行:21/23顺便提一下,其实-mwindows 这个参数我们已经不陌生了,第三部分中就用过它,这里的使用与之是完全一样的。具体可参见本系列文章
30、的第三部分。这样设置完成以后,就可以再Build 该 Caller 项目了,应该就可以通过:D。4.3 其它可能遇到的问题其它可能遇到的问题在对源代码或者编译参数进行修改了以后,最好使用 Eclipse 菜单的Project-Clean 功能对项目进行一下清理,以保证再次生成的时候我们的所有修改都是生效有。有时候,在对两个项目同时进行Clean 并Build 之后,会出现下面这样的提示:.:No such file:No such file or directory其实他的意思是说那个*.a 文件没有找到。这时候需要检查一下上文(4.2小节)提到的Archives 里是否有我们想要的.a 文件,如果我们的引用设置和Lib 项目的.a 文件都是正常的,说明这是Eclipse 资源同步的问题,这时候并没有关系,再对Caller 项目单独一下Build就行。这个问题不仅现在会遇到,后面我们还会看到,在使用资源文件(.res)生成.o 文件的时候,常常也会发生。通常是.o文件明明已经生成了,但Eclipse 的项目里却看不到,这时候只需要用F5 刷新(或者在项目上点右键选刷新)一下该项目就能看到我们需要的文件,22/23再编译连接就能正常。附:本文中的源代码项目下载(Inshion_Exa002.rar)23/23