You are on page 1of 58

上海天马

目 录

„ 第一章: 认识 CodeWarrior
„ 第二章: 工程和目标文件的显示和定制
„ 第三章: 编译
„ 第四章: 链接
„ 第五章: 调试
„ 第六章: 定制
„ 第七章: 库函数和 Microsoft Foundation Classes (MFC)
上海天马
第一章 认识 CodeWarrior

„ 1). CodeWarrior 能做些什么?


„ A).使用 C/C++ 进行编程
„ B).也支持 Java 开发
„ 本课程仅限于应用C/C++ 语言在 Windows 平台上使用 CodeWarrior 进行的开发.
„ 2). CodeWarrior 优点是什么?
„ CodeWarrior 能够自动地检查代码中的明显错误,它通过一个集成的调试器和编辑器来扫描
你的代码,以找到并减少明显的错误,然后编译并链接程序以便计算机能够理解并执行你的
程序.
„ 3).常用编程类型说明:
„ A). 应用程序(如:文本编辑器 WordPad )
„ B). 庞大的商业软(如:比如象 Adobe Photoshop,MicrosoftWord,CodeWarrior…)
„ C). 控制面板(control panels)<实际上是设置系统功能的一个简单界面,比如可以在控制面板中
完成.如:设置音量和鼠标移动速度这样一些参数.>
„ D). 动态链接库(dynamic linked libraries,DLLs)<提供一些很有用的被系统和应用程序共享
的函数.通常它们没有用户界面.>
„ E). 插件(plug-ins)<类似于DLLs,插件也是可供其它软件使用的小程序,但插件只能被特定的软
件使用.>
上海天马
第一章 认识 CodeWarrior

„ 4).CodeWarrior工具条介绍:

„ 4.1).文件菜单: 4.2).编辑菜单
上海天马
第一章 认识 CodeWarrior
4.3).查看菜单 4.5).工程菜单

4.4).查找菜单
上海天马
第一章 认识 CodeWarrior
4.6).调试菜单 4.7).VCS菜单

4.8).窗口菜单

4.9).帮助菜单
上海天马
第一章 认识 CodeWarrior

„ 5).CodeWarrior 集成开发环境的设置
上海天马
第一章 认识 CodeWarrior

„ 5.1).通用设置
„ 5.5.1).编译设置(Build Settings): 选择是否在执行编译之前保存已打开的源
文件,以及有多少内存被用于编译工作;
„ 5.5.2). IDE 之外(IDE Extras): 几个独立的设置.比如指定 CodeWarrior 是否
使用一个第三方的文本编辑器——因为集成的编辑器并不是很完美,这可以通
过指定一个你惯用的编辑器来替代它;
上海天马
第一章 认识 CodeWarrior

„ 5.5.3).插件设置(Plug-In Settings): 供插件开发商调试他们的插件;


上海天马
第一章 认识 CodeWarrior

„ 5.5.4).隐藏文件夹(Shielded Folders): 在这里指定的文件夹在工程设计期间,或


执行查找和比较操作期间,将要被忽略掉.如果在你的工程级有一个巨大的“数据”文
件目录,而你又不想让这些文件降低CodeWarrior 的操作速度时,这个设置就很管用
了;
上海天马
第一章 认识 CodeWarrior

„ 5.5.5).资料树(Source Trees): 用于指定 CodeWarrior 在编译程序时用不着的目


录.
上海天马
第一章 认识 CodeWarrior

„ 5.2).编辑器设置
„ 5.2.1).编辑器设置(Editor Settings): 几个用于定制编辑器显示、管理文本和
窗口的设置项;
上海天马
第一章 认识 CodeWarrior

„ 5.2.2).字体和制表符(Fonts and Tabs): 设置编辑器中的文本大小、字体、制


表符和其它显示设置;
上海天马
第一章 认识 CodeWarrior

„ 5.2.3).文本颜色(Text Colors): 用于指定特定语言元素(比如程序的注释)在编


辑窗口中的显示的颜色。
上海天马
第一章 认识 CodeWarrior

„ 5.3).调试器设置
„ 5.3.1).显示设置(Display Settings): 几个用于定制调试器显示的设置项;
上海天马
第一章 认识 CodeWarrior

„ 5.3.2).视窗化(Windowing): 设定调试器如何管理它的窗口(比如隐藏所有打开
的编辑器窗口);
上海天马
第一章 认识 CodeWarrior

„ 5.3.3).全局设置(Global Settings): 几个用于定制调试器在全局层次如何工作


的设置。比如当一个包含了程序调试信息的文件被打开时,是否启动这个程序;
上海天马
第一章 认识 CodeWarrior

„ 5.3.4).远程连接(Remote Connections): 允许通过 TCP/IP 进行远程调试。这


样,你就可以在地球的另一边调试你的软件了;
„ 5.3.5). Java 设置/Java 调试(Java Settings/Java Debugging): 允许你设
置特定的 Java 编程语言选项。本课程不涉及这部分内容.
„ 5.4). RAD 工具
„ 5.4.1). Layout 编辑器: 几个用于在 CodeWarrior 中定制快速应用程序开发工具
的使用的设置。正如你所见到的,CodeWarrior 有许多设置项和选项。设置完后点
击“Save”按钮保存你所作的修改,点击“Close”按钮将忽略你所作的所有修改。在进
入下一节课之前,多练习几次。最后请确认“默认的文本文件格式(Default Text File
Format)”(在编辑器设置面板中)保持为 DOS 设置。
上海天马
第二章: 工程和目标文件的显示和定制

„ 2.1).工程窗口
„ 当你启动 CodeWarrior 后,打开file,选择new,进入如下工程窗口界面.
上海天马
第二章: 工程和目标文件的显示和定制

„工程窗口用于管理整个工程的所有文件以及这个工程将要产生的目标(targets)文件。 Ⅰ). 一
个工程包含了足够的信息来编译一个或多个目标文件。
„ 所谓的目标(target)文件就是当你编译程序时,由 CodeWariior 创建出来的(通常是)一个应用
程序或库文件。一些程序可以编译产生多个目标文件。
„ 比如,你可以编写一个程序来创建一个 DLL 和一个调用该 DLL的主应用程序。在
CodeWarrior 的工程中,你可以定义一个目标来产生 DLL,定义另一个目标来产生应用程序。通
过这种方式,你的工程只需编译一次就可产生所有需要的目标文件或片断。
上海天马
第二章: 工程和目标文件的显示和定制

„ 在窗口的顶端有三个标签(tab)页:文件标签(如图2-2显示)、链接顺序标签页和目
标文件标签页(后两个标签页将在后续课程中讲述)。在这几个标签页的上方,有一
个用于选择要编译的目标文件的下拉菜单。在本例中,我们选择的是 Hello World
工程的调试版本。在下拉菜单的右边有几个图标,它们的存在允许你不必使用菜单
命令就可以方便地编译、链接和运行这个工程。

„ 注意: 在某些版本的 CodeWarrior 中,链接标签被称为段(segments)标签。有些人


可能在某些X86 的处理器上编程时使用的是分段(segmented)代码。但使用
windows 版的 CodeWarrior工具时就不是这样,这是产生的 X86 代码使用的是“扁
平的”(flat),或者叫做非分段的(unsegmented) 内存空间。

„ 顾名思义,文件标签页列出了在工程中所有可能用到的文件。你可以通过创建一些
组(用文件夹图标表示)来分门别类地管理这些文件,并可以帮助你方便地了解哪些
文件将被使用。在本例中,我们将 C 程序(以.c为后缀名的文件)全都放到一个叫做
Source 的组中,同时将库文件放到另一个组中,以便整洁明了地管理这些文件。
上海天马
第二章: 工程和目标文件的显示和定制

„ 在 Sources 组中有一个 main.c 文件。因为我们还没有编译这个工程,所以在每个


文件对应的 Code 和Data 栏中显示数字的都是零。一旦我们编译了这个工程,这
些数字就将显示出来,表示源码转换为机器代码后实际的代码量和数据量。可是,
库文件 ANSICX86.LIB 和 MWCRTL.LIB 后面显示的是 n/a 。这表示索虽然这些文
件被显示在这里,但是它们并不是 Hello World 目标文件的一部分。这两个文件是
用于不可调试(non-debugging)开发的,而本例不是这种情况。如果我们从菜单中
修改本例的目标文件为 Release(发布) 版本时,这两个文件就用得上了。这时这些
文件后面的 Code 和 Data 栏目就会显示相应的数值。

„ 注意 : 在 Data 和 Code 栏右端的 Target 栏目中的小子弹头也是用来表示该文件是否被当前


编译生成的目标文件使用到。再往右边去,是 Debug 栏(用一个绿色的小虫子表示),它是用
于告诉你对应的文件在编译时是否要产生调试信息。我们将在第五课中详细论述这部分内容。
最后,我们来看看在每一行最右端的弹出菜单,它是用于打开文件、更新源码、打开包含的
头文件等等操作的快捷方式,具体是什么才作,要看它所代表的项目的类型而定。

„ 现在来编译这个 Hello World 工程并看看编译后的工程窗口的情况。从 Project 菜


单中选择Make 命令来编译该工程。这将更新所有需要编译的文件并产生相应的输
出文件——在本例中是 Hello World这个应用程序。
„ 图 2-2: Hello World 程序的工程窗口(其中显示了所有包含于该程序中或用于编译
该程序的文件)
上海天马
第二章: 工程和目标文件的显示和定制

„ 从上图中我们可以看到,工程窗口发生了一些变化。Code 和 Data 栏都显示了当


前工程中对应项的相应的数字。如果你打算看看编译前后存放这些文件的目录的话,
你会发现编译后在该目录下产生了一些新的文件,如下图所示。
上海天马
第二章: 工程和目标文件的显示和定制

„ 在本例中,编译工程后在工程目录中产生了一个新的文件。这就是 X86 目标文件


输出——生成一个叫做Hello World x86 的应用程序。其它一些一直存在于这个目
录中的文件是: .mcp 文件—工程文件本省,以及 .c 源文件—包含了应用程序源码的
文件。Hello World Data 目录中还包含了由 CodwWarrior 生成的各种各样的支持
文件。现在你还不必去关心这些文件。如果你正在编译目标文件的调试版本,你会
看到更多的文件被产生出来,这些文件中可能包含着符号(symbolic)调试信息。集
成开发环境的调试器使用这些符号信息来记录在高层次源码中的操作轨迹。
„ 将在第五章中详细讲述这方面内容。
„ 现在你已经了解了这些文件是如何结合在一起被编译生成一个目标文件的。让我们
来运行这个目标文件并看看它的运行结果是什么样。你双击 Hello World x86 应用
程序,就会有下图所示的结果显示出来。
上海天马
第二章: 工程和目标文件的显示和定制

„ 该程序的源代码:
„ #include
„ void main(void) {
„ int c;
„ printf("Hello World on Windows!\n");
„ c = getchar();
„ }

„ 关于getchar()函数
„ 字符输入函数 getchar() 用在这里是什么意思呢?通常,当一个应用程序执行完毕后,
它就会终止,然后操作系统就会立即清除该应用程序输出.这样,当上述应用程序显示
完“Hello World on Windows!”后,为了避免系统立即将该程序地输出清除,我们在程
序中添加了一个 getchar() 函数,使程序在此处暂停,直到有键盘输入时整个程序会
终止.这样我们才有足够的时间来看清楚该程序的输出.
„ 这是一个正常的操作,而不是一个 bug.实际上,CodeWarrior也提供了一个适用于此
处的库函数,这个库函数中的 C 控制台 I/O 函数步不仅可以在程序显示完毕后锁定
应用程序,而且还可以让你将输出的文本信息存储到一个文件中去.
上海天马
第三章: 编 译

„ 第一步:理解编译阶段
„ 我们的前面的课程中已经学到,源程序输入完之后的工作就是要编译它。编译源程序就是计
算机把你所写(通常是用C 或 C++编写的)的源代码进行分解、分析,然后转化为机器语言。
机器语言是一种计算机能够理解阿语言,而且它运行起来比 C 或 C++ 也要快得多。编译的
大致过程如下:
„ 1. 用 C 或 C++ 编写代码:
„ #include
„ void main(void) {
„ int c;
„ printf("Hello World on Windows!\n");
„ c = getchar();
„ }
„ 2. 进行编译。 CodeWarrior 编译上述代码并把它翻译成机器语言,结果如下:
„ 符号名:
„ 1: _main 2: _@8 3: _printf 4: ___files 5: _fwide 6: ___get_char
„ =======================================================
========
„ SECTION SIZE = 0x0000003C; NAME =?.text DEFINED SYMBOLS: name = _main offset =
„ 0x00000000; type = 0x0020; class = 0x0002 00000000: 68 00 00 00 00 push offset _@8
„ 00000005: E8 00 00 00 00 call _printf 0000000A: 59 pop ecx 0000000B: 6A FF push -1
„ 0000000D: 68 00 00 00 00 push offset ___files 00000012: E8 00 00 00 00 call _fwide
„ 00000017: 85 C0 test eax,eax 00000019: 59 pop ecx 0000001A: 59 pop ecx 0000001B: 7D
上海天马
第三章: 编 译

„ 1E jge $+32 ; --> 0x003b 0000001D: 83 2D 2C 00 00 00 sub dword ptr


___files+44,100000023: 01 00000024: 72 0A jb $+12 ; --> 0x0030 00000026: FF 05 28
00 00 00 inc dwordptr ___files+40 0000002C: EB 0D jmp $+15 ; --> 0x003b 0000002E:
89 C0 mov eax,eax00000030: 68 00 00 00 00 push offset ___files 00000035: E8 00 00 00
00 call ___get_char0000003A: 59 pop ecx 0000003B: C3 ret near
„ ======================================================
======= SECTION
„ SIZE = 0x00000019; NAME = .data 00000000: 48 65 6C 6C 6F 20 57 6F 72 6C 64 20 6F
6E 20 57 Hello World on W 00000010: 69 6E 64 6F 77 73 21 0A 00 indows! DEFINED
„ SYMBOLS: name = _@8 offset = 0x00000000; type = 0x0000; class = 0x0003
„ ======================================================
========
„ 上述机器代码难于阅读,不要去管它。机器代码相比 C 或 C++ 而言,要难理解多了。但
是,计算机只能理解机器语言。只有将你的程序编译—或翻译—成机器代码,然后再执行
它,这样运行起来才能快一些,而不是每次运行时才去翻译它,那样运行速度就很慢了。
上海天马
第三章: 编 译

„ CodeWarrior 中编译选项的详细设置
„ 在正式开始编译源代码之前,CodeWarrior 还要对其做预处理。在这个阶段,是对 C 或 C++
代码进行编译前的一些准备工作。在编写程序的过程中,往往会有很多相同的P代码输入,于
是程序员使用一些快捷方式,比如所谓的宏(macros)来代替这些相同的输入。例如,你可以
使用 APPNAME 作为一个宏,来表示“Metrowerks CodeWarrior”,以此来减少输入的工作量。
预处理就是要把这些宏转换为它们实际表示的代码,此外还要替换一些定义符号(比如
#define THREE 3)为实际的源代码。为了更好地理解预处理所做的工作,你可以查看一下预
处理结果的清单。首先在工程窗口中选中一个源文件,然后从工程菜单中选择预处理项,你
就可以看到源代码进行了预处理之后,编译之前的结果清单了.
„ 定制 CodeWarrior 的编译方式
„ 在第二章中,我们已经了解了一些控制 CodeWarrior 编译代码的选项对话框。现在我们再来
详细地看看一些标准 C 和 C++ 编译器的设置。请你按照下面所学内容在你的 CodeWarrior
上进行实际的操作练习。
上海天马
第三章: 编 译

„ 从编辑菜单中选择 Hello World X86 setting 项来打开设置窗口。现在,点击图3-1中语言设置


类(Language Settings category)下面的 C/C++ 语言标签(C/C++ Language label),你就可以
看到C/C++ 语言设置对话框中的许多选项。我们逐个来学习这些选项,以便了解它们是如何
影响编译的过程的。 激活 C++ 编译器(Activate C++ Compiler): 这个选项允许你把所
有后缀名为 .c 的源文件当作 C++文件来进行编译。如果你想在 C 源码中使用一些 C++ 语
言的特色时,这个功能就很有用了;
„ ARM 一致性(ARM Conformance): 编译器要求你的代码遵循 ANSI C++ 的标准。但你
可以通过选中这个选项来指定你的编译器遵循“注释 C++ 参考手册”(Annotated C++
Reference Manual,ARM)中的标准; 允许 C++ 例外(Enable C++ Exceptions): 选中这
个选项将允许你在 C++ 代码中使用try/catch/throw 等块(blocks)。这些方法用于书写错误管
理器(writing error handlers);
„ 允许 RTTI(Enable RTTI): RTTI 表示 Run Time Type Information(运行类型信息)。这个
选项运息编译器判定一个 C++ 对象在运行中的类型。这是 C++ 的高级特色,在很多情况下
都是很有用的。如果你想了解更多关于 RTTI 的信息,请查阅你的 C++ 手册;内联深度/自
动内联/延期内联(Inline Depth/Auto-Inline/Deferred Inlining): 这些是关于源代码中
使用的内联函数的一些设置项。所谓内联函数,就是在编译时该函数的源代码将被直接插入
到程序体中,而不是产生这个函数的调用。在某些情况下,使用内联函数可以提高代码的性
能。这是编译器的一个高级设置项;
„ 字符串池(Pool Strings): 通常,编译器将编译后代码中的所有字符串对象存储到它们自
己的数据空间中。如果你想将所有的这些字符串存放到一个数据空间中,就应该选中此项。
如果你的源代码中有非常多的字符串(比如上面我们提到的 APPNAME 宏),那么你就应该选
中此项来节省内存空间。这个功能只能在使用 PowerPC 的 Mac OS 平台上编程时使用;
„ 不重用字符串(Don't Reuse Strings): 所谓“重用字符串”,就是指当你的程序中有几个完
全一样的字符串时,编译器会将它们全都存放到同一个数据空间里。但是,有时你可能想修
改某个字符串,这就会造成其它和要修改字符串共享数据空间的字符串也要被修改了。如果
你想避免这种情况,就要选中这个选项。这样,即使程序中有完全一样的字符串,它们也将
存放到不同的数据空间中;
上海天马
第三章: 编 译

„ 要求有函数原型(Require Function Prototypes): 建议最好选中此项。使用


函数原型可以帮助编译器在检查传递给函数的参数类型时发现代码中的错误。所谓
函数原型就是在程序的前端对函数进行声明。也就是说,你应当在使用一个函数之
前,定义或声明这个函数。既然这个选项这么好,那么什么时候应该关掉它呢?通
常是,当你使用一些老版本的 C 进行编程时,并不需要对函数进行事先声明,这
时你就应该关掉这个选项来检查整个程序代码。你一定愿意在程序前端书写函数原
型,并选中此选项,因为它能帮助你解决这么多的编码错误;
„ 允许支持布尔变量(Enable bool Support): 为了使用 C++ 的布尔变量——
true (真) 和 false (假) 这两个关键字,必须选中此项;
„ 允许支持wchar_t(Enable wchar_t Support): 为了使用 C++ 的内置类型
wchar_t 而不是 char 类型来表示字符类型,必须选中此项;
„ 严格遵循ANSI/只能使用 ANSI 关键字(ANSI Strict/ANSI Keywords Only):
默认情况下,编译器允许你使用 Metrowerks 扩展和 C/C++ 语言的附加关键字。
但是如果你想在这种情况时编译报错,那么就应该选中这两项。这样,编译出来的
程序就是 100% ANSI 兼容代码;
„ 扩展通配符(Expand Trigraphs): 默认情况下,通配符是不允许的。为了能够
使用通配符,就要选中此项。所谓通配符,就是在你的源代码中代表字符常量的方
式。例如, '????' 就是一个通配符;
上海天马
第三章: 编 译

„ 多字节敏感(Multi-Byte Aware): 如果你是有能够的编程语言要求使用多字节字符(例如 Kanji 或


Unicode),就要选中此项。这样编译器才能正确地处理源代码中的多字节字符;
„ 指示到 SOM (Direct to SOM): 这是 Macintosh 平台上才有的功能,它允许你在 CodeWarrior 中直接
创建 SOM 代码。SOM 是一种使用于苹果机上的开放文档环境的代码类型,但现在已没人用了;
„ 使用 CR 为换行符(Map Newlines to CR): 这个选项允许你交换 '\n' 和 '\r' (这是用于标识源码行结束
的符号)。此选项只对 Mac OS 上的编程有用;
„ 不严格的指针类型规则(Relaxed Pointer Type Rules): 选中此项将把 char *, unsigned char *, void
*和 Ptr 当作是同一种类新。当你从另一个并没有正确管理指针类型的源代码中,或者是从一个使用还不
能正确支持这些类型的老编译平台上开发的源代码中继承代码时,这个选项就很有用了;
„ 枚举类型总是整型(Enums Always Ints): 通常情况下,编译器将一个枚举类型分配与之最接近的类
型同样的空间。如果你想使枚举类型的空间总是和整型一样,那么就要选中此项。所谓枚举类型就像这样:
enum {itemone, itemtwo = 7, itemthree}。其中,itemone 等于 0,itemtwo 等于 7,itemthree等于 8;
„ 使用无符号字符类型(Use Unsigned Chars): 选中此项将把所有字符数据类型当作无符号字符类型来
处理;
„ EC++ 兼容模式(EC++ Compatibility Mode): 使用 CodeWarrior 编译嵌入式 C++ (EC++) 代码
时,要选中此项。请注意,此时 C++ 中的诸如模板(templates)、例外(exceptions)和其它一些 C++ 的高
级功能就不可用了。具体情况请查阅 C++ 手册;
„ 允许 Objective C(Enable Objective C): 为了使用 Objective C (在 NeXT 计算机操作系统上很著名
的编程语言),要选中此项。此选项只能在 Mac OS 下只用;
„ 前缀文件(Prefix File): 如果需要在每个源文件中包括一个头或预编译头文件,就要将该文件名输入在
此处。适用情况:当所有源文件都要访问一个特殊的定义,但你又不想在每个源文件中键入 #include来包
括该定义时,使用此选项很方便。
„ 注意: 上述许多选项在 Mac OS 和 Windows 平台上的 CodeWarrior 编译器版本中都是一样的。但根据我们
在上面对这些编译器选项的描述可知,一些选项在两个平台上还是有一些不同的。然而,C 和 C++ 时平
台无关的编程语言,因此大多数概念都是可以应用于任何平台的。
上海天马
第四章 连 接

„ 第二步:连接程序各部件
„ 当你的程序编译完毕以后,接着就要使用连接器来把这些组成你的程序的各个文件连接起来。
„ 连接器是用来组合各个源文件被编译后得到编译代码的,同时还要将这些文件与它们所需要
的库连接在一起。连接确保了每片代码都知道如何去找到你程序中的其它元素。例如,连接
器修改机器代码以便使用MSL 库函数中的 printf() (该函数用来实现功能强大的控制台输入/
输出)来替换你在源文件中使用的 printf()函数调用。
„ 当你编写一个程序时,常常将代码写成函数并存放在不同的文件中,然后将这些文件编译得
到单个的输出文件。就像我们在前面使用的 Hello World 这个程序,它的输出文件是一个应
用程序。但是在某些时候,同一个程序中使用的函数在输出时不一定是存放在同一个输出文
件中的。例如,假设你编写一个应用程序时,其中包含了许多被程序的多个部分重复使用的
代码,你就可以将这些被重复使用的代码编译成为一个可共享的动态链接库(DLL)。这样,该
应用程序仍然可以访问到这些代码,但是它就需要弄明白应该到哪个文件以及如何找到这些
它需要使用的函数。这种情况,就需要做一些连接的工作了。
„ 连接的类型在程序的编制中,一个连接就是一个指针,指向一个象编译函数这样的对象,或
者指向一个变量或一个数组这样的数据内容。连接有两种方式:硬连接(hard linking)和软连
接(soft linking)。
„ 硬连接发生于连接过程中,说明代码的时候。换句话说,如果一个函数被使用了,在连接时
连接器确切地知道这个函数在哪里并创建一个连接把这个函数连接起来。
„ 软连接(也称为弱连接)发生于进行连接时,一些代码可以不需要进行说明,因为你知道这些
代码位于一个DLL 中,并在运行时可以从该 DLL 中进行调用。在这种情况下,连接器会告诉
应用程序到哪里去找它所需要的代码。
„ 软连接也是计算机操作系统中许多元素使用的方法。接下来,我们一起来学习一些关于连接
器的选项设置。
上海天马
第四章 连 接

„ A 连接Detailed Look at Linking


„ 为了将来能更好地领略 CodeWarrior for Windows 平台的卓越功能,你首先需要了
解如何配置CodeWarrior 的连接器来满足你的要求。
„ 根据你的要求来配置连接器
„ 本教材使用的示例是运行在 x86 平台上的 CodeWarrior 的连接器设置面板(如图4-
1)。但是在这其中使用的很多术语也是适用于其它平台上的 CodeWarrior 连接器的。
上海天马
第四章 连 接

„ 通过选择编辑菜单中的“工程名”项来打开这个设置窗口。(“工程名”是指当前的活动工程——在本例中
„ 就是 Hello World x86),然后点击设置窗口中的 x86 连接器(或类似的名字)标签。
„ 下面我们来看看一些连接器设置项:
„ 入口点用法(Entry Point Usage): 在 Windows OS 体系中,每一个代码模块都有许多可能可以或者不
„ 可以选择的入口点,这取决于你所编译的代码类型。这些入口点的自然属性依赖于你正在编写的程序
„ 的输出文件(应用程序、库或 DLL )的类型和其它的一些因素。当一个应用程序需要调用一个 DLL 函
„ 数时,主机操作系统就使用这个入口点信息来正确地调用该 DLL 地初始化函数。大多数情况下,你
„ 应当设置此选项为默认方式(如图4-1所示)。这将让 CodeWarrior 根据你在目标文件设置面板中选择
„ 的目标文件类型,来自动地为输出文件设置正确的入口点;
„ 子系统(Subsystem): 子系统有三种选择:Native、 Windows CUI 和 Windows GUI。Native 选项是
„ 用于开发驱动程序和其它异种系统模块的; Windows CUI 选项是用于开发使用控制台风格用户界面
„ ( console-style user interface,所谓的CUI )的应用程序的;Windows GUI 选项用于开发使用
„ Windows 图形用户界面(Windows graphic user interface,所谓的 GUI )的应用程序的。因为我们是
„ 用的示例程序是简单的基于控制台的 Windows 应用程序,所以我们选择了 CUI 子系统。通常情况
„ 下,CodeWarrior 会根据你在开始创建工程时选择的工程模板来自动地设置子系统的选项;
„ 子系统 ID/用户 ID(Subsystem ID/UserID): 和子系统项一样,这个选项也是由 CodeWarrior 自动
设置的。具体系统对应的 ID 为:Windows 3.1,Windows 95 和 Windows NT 3.5 的 ID 为 3.10,
„ Windows NT 4 的 ID 为 4.00;
„ 生成连接映射(Generate Link Map): 这个选项允许你生成一个文本文件,其中包含了程序中使用到的
„ 所有的类和函数的详细信息。当需要通过匹配变量或函数名的地址来调试代码时,这个选项就非常有
„ 用了;
„ 生成 SYM 文件(Generate SYM File): 这个选项允许你在连接过程中生成一个符号文件。大多数的调
„ 试器在进行调试时需要一个符号文件来逐步调试你的源代码。我们将在第五课中详细讨论这个内容。
„ 此外,你还可以通过选中生成 CV 信息项(Generate CV Info item)来生成一个可用于 CodeView 的符
„ 号文件。CodeView 是一个流行的 Windows 调试工具;
上海天马
第四章 连 接

„ 生成 CV 信息(Generate CV Info): 生成一个可用于 CodeView 的符号文件。CodeView


是一个流行
„ 的 Windows 调试工具;
„ 命令文件(Command File): 这个选项要你选择一个用于指示复杂的连接选项设置的文本
文件。该文件称为连接器命令文件。它被使用来指定要导入和导出哪些符号。除非你正在编
写一个特殊目的的代码,你才不需要一个连接器文件。
„ 正如你所知的,连接器的设置过程是非常复杂的。但是,在多数情况下,你不需要修改连接
器的默认设置。Metrowerks 公司的开发人员已经帮助你很好地解决了这个问题。
上海天马
第五章 调 试

„ 关于调试
„ Purging pesky pests proves productive for programmers!
„ 调试就是在你的程序代码中找到一个问题并着手去解决它的过程。不管是谁,在编程时都难
免出现一些输入或程序逻辑上的错误,一旦出现这种问题,很可能你想破了头也找不到错误
在哪。这个问题可能只是一个输入上的小错误或者只是一个变量用错了,因此你很难发现它。
但是因为这个错误的存在使得你的程序无法实现预期的功能。有时候会更糟糕,以致你的机
器都崩溃了。这时,你就必须借助调试来解决问题。
„ CodeWarrior 带有一个集成的调试器,可以让你在 CodeWarrior 主窗口中打开一个窗口来进
行调试工作。使用调试器的方法是,从工程菜单中选择 Enable Debugger 项,然后重新编译
你的目标文件。完成上述步骤后,你的程序就会在调试窗口中运行,此时你就可以隔离并改
正你找到的任何一个问题了。
„ 通常进行调试时总要生成源程序的一个调试目标文件。该目标文件的源文件保持不变,但是
需要预先设置置一些选项才能产生该程序的调试版本。通过点击工程窗口的弹出菜单中的调
试目标文件,你就可以进入调试状态。
上海天马
第五章 调 试
上海天马
第五章 调 试

„ 上图显示了 Hello World 这个程序在 CodeWarrior 调试器中进行调试时的情况。为了能够更


方便地演示调试器的工作过程,我们在程序中添加了一小段循环代码(其中使用了 i、x 和 y
等三个变量)。调试器允许对代码执行单步逐行调试。当你在代码中移动时,你还可以查看程
序中所有变量的值。在这种“慢速移动(slow motion)”的方式下调试程序,你可以非常清晰地
查看到代码的运行情况并很容易地解决问题。
„ 但实际情况是,不是所有的问题都很容易解决的。有些问题就有可能要花费你长达数周的时
间去解决。不管是经验多么丰富的编程老手,同样不可避免地要遇到这样的问题。作为一个
初学者,你更容易遇到这样的问题,但是,你千万别被这种情况吓倒。请记住,从错误中学
习,你能学到更多的东西。
„ 请注意在调试器窗口左上角的那些按钮,它们是用于帮助你进行调试工作的。这些按钮从左
到右分别是:
„ 运行程序(Run Program)、停止(Stop)、退出(Kill (Quit))、跳过(Step Over)、转入(Step Into)
和转出(Step Out)。最后两个命令按钮是让你决定在单步调试程序时,如果遇到一个函数,
是否要进入函数内部进行代码调试。或者你也可以使用跳过(Step Over)命令让该函数一次执
行完毕,而不进入函数体中单步调试函数的代
„ 码,这样可以节省一些时间。如果你不能肯定函数是否正确无误,那么你可以转入(step into)
该函数体内部对其进行单步调试。对于初学者,你应该单步调试每一个函数,至少可以练练
手嘛!
上海天马
第五章 调 试

„ 图 5-1 所示的调试窗口包含三个主要部分:
„ 栈窗格(The Stack pane):位于左上方的窗格是显示调用栈(也叫做调用栈的记录)的区
域。当你在单步调试源码的过程中调用了多个函数时,在这个区域就显示出调试到达当前状
态之前调用过的函数名清单。这个清单会随着你的调试过程,根据你是否转入函数内部的情
况随时增减;
„ 变量窗格(The Variables pane): 位于右上方的窗格是显示变量名和其值的区域。其中显
示的是各个变量的名字和它们的值,而且还可以依据变量的类型让你查看(或修改)这些数据。
在图5-1中显示的Hello World x86 程序这个例子中,有四个变量:c,i,x 和 y。当你在代码
中执行单步调试时,这些变量的值就会根据程序执行的过程实时地更新。例如,在调试过程
中,你可以注意到后三个变量是如何取得它们的值的(这些值是在循环代码中赋给这些变量
的),而变量 c 显示的是一个无意义的值(因为你还没有给 getchar() 输入任何值)。你可以使
用这个窗格来发现不正常的变量值,从而发现程序设计上的错误这对于程序的调试成功,非
常关键;
„ 源代码窗格(The Source pane):位于下方的窗格显示了 Hello World x86 这个程序的 C
语言源代码,它也可以用来显示该代码的汇编语言版本。随着调试的深入进行,仅仅是程序
的 C 语言代码可能不能提供足够的调试信息,这是你就需要查看该程序的汇编语言代码。你
可以通过该窗口下端的弹出菜单来选择查看程序的源代码、汇编代码或者两者的混合显示。
„ 你可能已经注意到在源代码窗格左边的红色停止标记,该标记表示这是一个断点,它用于告
诉调试器在此处停止执行程序。此功能可以帮助你很方便地快速到达程序中地某一位置,然
后从此位置处开始调试程序。
„ 当你设置了一个断点,调试器运行到断点所在的行就停止下来,等待你的控制命令。在某行
程序左边显示的蓝色小箭头是当前程序的计数器,它表示指向的程序行为即将要执行到的语
句。在图5-1中,我们已经设置了一个断点以便程序执行到完源代码中的循环块后在第二个输
出语句前停下来。设置断点的操作也很简单,只需在你希望调试器停止的程序行的左端点一
下鼠标即可。
上海天马
第五章 调 试

„ 下面我们来看看关于 CodeWarrior 调试器的一些参数设置。


„ 全局调试器参数设置
„ 通过选择编辑菜单中的“Preferences”项,可以看见 CodeWarrior 调试器有许多全局的参数设
置。
„ 设置内容
上海天马
第五章 调 试

„ 设置显示面板(见图5-2)包含了一些决定调试器窗口上如何显示信息的参数设置。当你刚开始
使用调试器时,你可以在这里把调试器窗口上的某些文字设置得大一些或小一些,或者用一
些特殊的颜色来显示它们。
„ 颜色设置允许你选择在源代码中用于突显观察点(watchpoints)和变量名的文字颜色。这种设
置非常有用,可以帮助你在调试代码时很容易地观察到观察点或变量值的变化。观察点可用
来帮助你在整个程序中跟踪某个值并将其显示在一个窗口中。
„ 其它设置的用途都解释得很明白了,你也不需要去更它们,默认设计就可以了。当你对调试
器了解得更多了一些时,你才可能会的想去修改这些设置。
„ 关于视窗的设置
上海天马
第五章 调 试

„ 在调试程序的过程中,你会发现桌面上很会就挤满了许多打开的窗口。关于视窗的设置(见图
5-3)允许你设定在调试中隐藏或显示某些特定的窗口来管理这些窗口。默认的设置是隐藏非
调试用的窗口,这在大多数情况下就可以了,不必修改它。
„ 全局设置
„ 全局设置窗格(如图5-4所示)包含了一些用于控制调试器操作方式的选项
上海天马
第五章 调 试

„ 调试过程中缓存修改后的文件这一设置是用于决定修改后的文件需要缓存多长时间用的。缓
存文件能够提高调试器的速度,但是要牺牲一些磁盘空间。
„ 其余的设置解释得很清楚了。如果你只是一个初学者,那么默认设置就可以了。
„ 远程连接
上海天马
第五章 调 试

„ 最后是远程连接设置(见图5-5)。该设置面板用于设置通过一个 TCP/IP 网络进行远程调试。这是一些高级


设置,作为初学者,使用默认设置就可以了。
„ 至于 Java 设置和 Java 调试面板用于使用 Java 语言进行编程的情况的,本课程不涉及这个内容。你可以
学习一些相应的课程。
„ 目标文件和工程特定的调试器参数设置
„ 以下是关于被调试的目标文件和工程的设置项。当在 CodeWarrior 的工程窗口的目标文件标签中有一个目
标文件被选中时,你再选择编辑菜单中的工程名设置(Project Name Settings)项即可看到这个设置窗口。
上海天马
第五章 调 试

„ 调试器设置
„ 重定位后的库...的位置(Location of Relocated Libraries, etc): 如果你正在调试的文件被移到其它
位置了,或者你正在通过一个 TCP/IP 网络来进行远程调试,你就必须将这些文件所在的目录输入到这个
文本框中;
„ 在应用程序启动时在临时断点处停止(Stop at temp breakpoint on application launch): 默认情况
下,这个选项在程序的起始位置中断调试器的运行。但你也可以设置为可在任何断点处中断;
„ 自动查找目标库(Auto-target Libraries): 选中这个选项可以自动地访问库。此选项用于正在调试的
代码是一个库的一部分时,当你调试这些代码时,调试器将“做应做的事”(例如装载库并调用任何初始
„ 化函数);
„ 记录系统消息(Log System Messages): 这个选项用于强制将所有的系统消息写入一个记录文件中。
„ 当你遇到代码导致系统崩溃,并因系统崩溃又看不到屏幕显示时,就很有用了。当你重启机器后,你
„ 可以从记录文件中查看导致系统崩溃的消息。特别是今后你调试一些大型程序时,记录文件就很有用
„ 了,所以一定要学会读懂记录文件!
„ 数据更新时间间隔(Data Update Interval): 选中这个选项并给它设置一个值,这样你就可以决定数
据查看(data view)多长时间更新一次。数据查看更新得越频繁,调试器显示的数据值就越新;
„ 缓存运行中的符号文件(Cache symbolics between runs): 在调试器运行时,符号文件(在编译过程
中产生的一种文件)将被缓存起来。这可以提高调试的进程;
„ 在观察点处停止(Stop at Watchpoints): 选中此项,当观察点值为真时就中断调试。观察点和断点一
„ 样是很有用的。不同的是,断点每次都是在一个特定的代码行处停止下来,而观察点是监视一个变量
„ 或内存的一块区域,当此被观察的对象发生改变时,它就中断调试过程。这和 VC 中的条件断点相
„ 似,都是在设定的条件被满足时中断调试过程的。这是一个很有用的调试工具。
上海天马
第五章 调 试

„ x86 异常(Exceptions)
上海天马
第五章 调 试

„ 当你调试有问题的代码时, CodeWarrior 调试器会截取到由程序的 bug 引起的某些奇怪的操


作(即所谓的异常——Exceptions)。 IDE 会将这些异常传递给一个特殊的代码——一个被称
之为处理器的东西——由它来处理这些异常问题。
„ 但是,对于大多数的异常,调试器只是简单地中断它的工作而已。为什么会这样呢?
„ 如果你正在做一个高级开发,例如开发一个系统库或一个设备驱动程序,你可能想测试一下
这些代码是如何处理这些异常的。只有调试器不截取这些异常时,你才能这么做。如果为了
一些特定的原因,你希望调试器抓住某些特定异常发生时的控制("seize control of the
moment" for specific exceptions) ,你就应该在这个设置面板上做一些设置。在该面板上显
示的异常是 CodeWarrior 的集成开发环境可以处置的情况。点击那些你希望由调试器来处理
的异常情况,然后点击“保存”按钮保存设置。就像前面提到的,这是很高级的编程设置,因
此我们在这将不作详细讨论。总之,CodeWarrior 的调试器是一个非常先进的,而且很易于
使用的附件。如果你学好了调试器的使用,它将会成为你开发软件的最重要的一个工具。
„ 另外还有“其它的可执行程序”和“远程调试”设置面板,它们是针对高级用户设置的,本课程不
打算再作介绍。如果你需要同时调试多个可执行程序或通过 TCP/IP 网络来调试程序的话,
你可以自行参看这几个设置面板。
上海天马
第六章 定 制

„ 概述
„ 这将是最简单的一课,但它却能够帮助帮助你更好地组织你的思想和开展工作。
„ 正如我们在第一课中学到的,可以有许多中方式来为手头某个特定的任务定制 CodeWarrior。
„ 你可以定制 CodeWarrior 的外观和许多设置项,以便使得编译、连接和调试你的程序变得更快、
„ 更简单。
„ 下面我们来看看可用于帮助你更有效地使用 CodeWarrior 的定制选项。因为定制
„ CodeWarrior 会改变 IDE 的所有行为,所以我们可以想到在编辑菜单下找到这些设置项。在那儿
„ 你将找到选择、命令和键绑定(Key Bindings)等菜单。点击其中的命令项就会显示定制 IDE 命令
„ 设置的窗口。定制 IDE 命令的面板包含两个主标签页。命令标签页允许你很容易的定制出现在每
„ 个 CodeWarrior 菜单中的命令。通过该标签页你也可以修改在内置的文本编辑器中使用的命令,
„ 例如选择文本和移动光标等命令。在这个设置窗口中,你还可以创建任何用于触发某个菜单命令
„ 项的组合键(也称之为键绑定——key binding),以此来启动一个应用程序,或者执行一个脚本。当
„ 然,你也可以设定一个某个命令项是否出现在一个菜单中。
„ 定制 IDE 命令的面板中的另一个标签页是工具条项目标签页,在这个标签页中你可以看到在
„ CodeWarrior 的工具条中显示的项目,例如显示在每个文本编辑器窗口上方(或下方,取决于你的
„ 参数设置)。
„ 在工具条项目标签页中,你只需点击一个工具条图标然后把它拖到主菜单下面的工具条或者
„ 文本编辑器窗口的工具条中,就可以往相应的工具条中增加一个命令。还可以把工具条中的一个
„ 图标拉到工具条的最后。从 CodeWarrior 的窗口菜单中的工具条子菜单中选择重设窗口的工具条
„ (Reset Window Toolbar) 或重设浮动工具条菜单项,还可以重新设置该工具条。
上海天马
第六章 定 制

„ 在大多数情况下,CodeWarrior 的默认设置就可以满足你的要求了。偶尔你也可能发现一个
„ 通过改变一个菜单或工具条的方式来自动完成一些任务。关于 Codewarrior 的定制,你可以参考
„ 它的在线文档获得更多的信息。
„ CodeWarrior 定制示例
„ 通过定制 CodeWarrior,你可以增强你的工作环境和提高工作效率。 除了对菜单和工具条的
„ 简单修改之外,你可能还想只需点击一个图标或键入一个组合键就可以执行一个脚本或启动一个
„ 应用程序。有时当你正在参与一个非常庞大的开发项目的时候,需要做一些定制工作来解决自动
„ 设置带来的混乱问题。例如,你可以创建一个脚本来完成以下这些工作:
„ 自动删除编译过程中产生的多余的文件;
„ 将输出文件复制到一个本地或网络上的目录中以做备份;
„ 为你的工程创建一个安装应用程序。
„ 对于 Windows 用户而言,可以通过 VBScript,Perl或其它使用通用对象模型(Common Object
„ Model,COM)接口的脚本语言来驱动 CodeWarrior Pro 5 IDE 完成一系列复杂的操作。如果使用
„ VBscript,你还需要一个可以执行 VBScript 的的应用程序(如 Internet Explorer 5),或者是一个
„ Scripting Host 工具——可以从以下网址下载 http://msdn.microsoft.com/scripting/windowshost/。
„ 下面的 VBScript 脚本用于指导 CodeWarrior IDE 删除当前工程中的所有目标(object)文件,以
„ 便执行一个“干净的构建(build)”,然后再执行构建工作(编译和连接操作)。该脚本还打开一个编
„ 辑器窗口来显示操作结果(成功或失败的)的总结。这个脚本是有点长,但设计得很好,因为其中包
„ 含了许多用于错误检查的代码。
„ ' 文件名:Build.vbs
„ ' 作者: Jim Trudeau, Metrowerks
„ ' 以及版权声明信息
„ option explicit
„ '所有的变量都必须进行声明
„ dim CW
上海天马
第六章 定 制

„ dim project '默认的工程


„ dim textDocument '用于保存报告的文本文档
„ dim textEngine '用于处理文本的对象
„ dim eol '行尾字符格式
„ dim result '返回的值
„ eol = chr(13) '设置行尾字符
„ '创建 CodeWarrior 的一个实例
„ set CW = CreateObject("CodeWarrior.CodeWarriorApp")
„ '创建一个文本文档并获得其引擎(Engine)
„ set textDocument = CW.OpenUntitledTextDocument()
„ set textEngine = textDocument.TextEngine
„ '得到默认的工程
„ set project = CW.DefaultProject
„ '错误控制
„ if TypeName(project) = "Nothing" then
„ textEngine.InsertText("Script operates on default project." &eol)
„ textEngine.InsertText("There must be at least one open project." &eol)
„ else
„ dim target '当前目标
„ dim buildmessages '错误和警告
„ '*** 获得当前目标
„ set target = project.GetCurrentTarget
„ textEngine.InsertText("Build Information" &eol)
„ '显示名字
„ result = target.name
„ textEngine.InsertText("Building target " &result &eol)
„ '*** 删除所有的对象代码目标
上海天马
第六章 定 制

„ RemoveObjectCode true
„ '*** 获得构建代码后的消息
„ set buildMessages = target.BuildAndWaitToComplete
„ ProcessMessages (buildMessages)
„ end if
„ '========================================================= '
„ ProcessMessages - get errors and warnings, process them ' receives build
„ messages
„ '=========================================================
„ sub ProcessMessages (messages)
„ dim result '返回值
„ dim messageList '消息收集
„ '*** 获得错误的数量
„ result = messages.ErrorCount
„ if result = 0 then textEngine.InsertText(eol &"Build Succeeded." &eol)
„ else textEngine.InsertText(eol &"!!!BUILD FAILED!!!" &eol)
„ '*** 显示错误的数量
„ textEngine.InsertText("Number of errors: " &result &eol)
„ '*** 获得错误清单
„ set messageList = messages.Errors
„ '*** 处理错误
„ ProcessMessageList (messageList)
„ end if
„ '*** 检测是否有警告信息
„ result = messages.WarningCount
上海天马
第六章 定 制

„ '*** 显示数量
„ textEngine.InsertText("Number of warnings: " &result &eol)
„ '*** 取得警告信息并处理之
„ if result then
„ '*** 获得警告信息清单
„ set messageList = messages.Warnings
„ '*** 处理警告信息
„ ProcessMessageList (messageList)
„ end if
„ end sub
„ '========================================================= '
„ ProcessMessagelist - loop through messages, report info ' receives message
„ collection, could be errors or warnings
„ '=========================================================
„ sub ProcessMessageList (messageList)
„ dim result '返回值
„ dim index '循环计数器
„ dim message '个人信息
„ '*** 遍历消息清单
„ for index = 0 to messageList.Count-1
„ '*** 获得个人信息
„ set message = messageList.Item(index)
„ '*** 获得消息文本
„ result = message.MessageText
„ '*** 显示消息文本
„ PDA开发Page 5 of 10
上海天马
第六章 定 制

„ textEngine.InsertText(result &eol)
„ ****在错误中忽略一行(skip a line between errors )
„ textEngine.InsertText(eol)
„ next
„ end sub
„ 因为使用了微软公司的 OLE/COM 查看器工具,这个 IDE 支持许多 COM 对象。一个脚本语
言可以使用这些对象来与 CodeWarrior IDE 进行通信。关于 CodeWarrior 定制与脚本机制,
还有很多优秀的功能,但在这里就不详述了,因为 CodeWarrior 把这些功能实现得非常好。
打开上面所描述到得窗口自己看看吧!当你熟练使用了 CodeWarrior 的一些功能之后,你会
发现它是非常的易用!
上海天马
第七章 库 和 Microsoft Foundation Classes (MFC)

„ 库
„ 库是什么?这是一个你必须知道如何回答的问题!一个库就是一个包含了你程序运行时需要调用的
„ 函数的文件。在库中提供的典型函数有:文件和屏幕的 I/O 函数,内存管理服务,3-D 图形显示以及
„ 科学计算函数。使用库可以缩短你的开发时间并简化你的应用程序。在开发程序当中,你会经常地使
„ 用到库。以下是几种在编程中使用库的方法:
„ 将你需要用到的函数写在一个源文件中,然后把它编译成为一个库或 DLL;
„ 使用别人提供的库;
„ 使用一个其他人提供的共享库(或 DLL)。
„ 编写你自己的库或 DLL
„ 第一种使用库的方法很简单。你只需在一个 C 或 C++ 源文件中写入源代码,然后编译、连接并执
„ 行它。这是我们在本课程中早已学到的知识。就这样你就可以创建你自己的一个库,就这么简单!
„ 使用别人的库
„ 使用别人提供的库稍稍有些不同。由第三方开发商提供的库通常包括以下几个文件:库文件(通常
„ 是以 .lib 为后缀名的文件),一个头文件(后缀名为 .h) 以及(我们希望有但不一定有)一些文档(后缀名
„ 为.doc)。头文件是用于让编译器将你的程序中使用的函数与库中的函数匹配起来的。你只需将头文件
„ 包括到你的源文件中,然后就可以象调用操作系统的函数一样来调用库函数了。在大多数情况下,通
„ 常将 .h 和 .lib 的文件放置于源文件目录中,就像 CodeWarrior 定义的一样。这个路径通常在你的工
„ 程文件所在的目录,或者其下的子目录中。需要注意的是,CodeWarrior 提供的某些特定的库,例如
„ 它的 MSL,就不是放在你的工程所在的目录中。实际上,CodeWarrior 有一个特定的存取路径,叫
„ 做 system paths, 它指向 CodeWarrior 自带的库和头文件存放的目录。
上海天马
第七章 库 和 Microsoft Foundation Classes (MFC)

„ 使用一个共享库:
„ 第三方厂商将库函数与它们的产品打包起来发行,而不是以源文件的方式发行这些库。如果你是一
„ 个开发商,使用这样的方式来发行你的库会更安全一些,特别是你希望由此来保护你的知识产权时。
„ 但是这种方法也存在一个问题,就是如果在库中存在一个 bug 的话,用户是没办法对之进行修改
„ 的,只能从开发商那里取得一个修正后的版本。但是这做起来也有许多困难。
„ 共享的 DLL:
„ DLL 和库文件非常相似,两者之间唯独的不同就是库文件通常都会被编译并连接到你的应用程序
„ 中,而 DLL 则是存放在你的系统目录下或者是在编译后的应用程序的目录下的一个独立的文件。当
„ 应用程序运行时,它会自己去找到该 DLL 并使用它的服务。DLL 文件的后缀名为 .dll。
„ 使用共享的DLLs 的好处:
„ DLL 的优点就是它能够被共享。那么,共享的好处在哪里呢?首先,可以让多个应用程序使用一个
„ DLL。当几个程序都使用一个占用很大磁盘和内存空间的 DLL 时,就很有用了。另外,如果一个
„ DLL 包含了一个 bug,然后被修正了,那么所有使用这个 DLL 的程序都会被自动更新,这样就可以
„ 大大地节约你的开发时间。那么哪种库应该由多个应用程序共享呢?比如操作系统中的每一个视窗就
„ 是使用共享的 DLL 得来的。
„ 使用共享 DLL 需要注意的地方:
„ CodeWarrior IDE 的 CD-ROM 中有许多库,在因特网上还有成千上万的库。记住,当你使用第三
„ 方厂商的库时,千万要先查查毒。这就如同出门前要关门一样的有必要。
„ CodeWarrior 自带的库分为两类。一个是 MSL,它提供 ANSI C/C++ 的标准函数。MSL 已经被移
„ 植到许多平台上了,因此可以在 Windows,Mac OS 和 Solaris 系统中使用它的函数。另一个是供特
„ 定平台使用的库。例如,在 Windows 版的光盘中,你可以发现提供了使用 Windows APIs 和 MFC
„ 库的Windows 32 支持库,它提供了编写面向对象的 Windows 应用程序的框架。随着你的编程经验
„ 的增长,你将发现这些特定库的更多的用途。
„ MFC是什么:
上海天马
第七章 库 和 Microsoft Foundation Classes (MFC)

„ Microsoft Foundation Classes (MFC) 提供了快速开发 Windows 应用程序的函数集。虽然你已经


„ 可以自由地直接调用 Win32 APIs,但使用 MFC 会更简单一些,因为 MFC 提供了诸如创建一个窗
„ 口或者使用智能默认设置和错误检查代码来编写文件这样的基本服务。MFC 可以在 Windows 版的
„ CodeWarrior 光盘中找到,但不一定是最新的版本。你可以查看 Metrowerks 的帮助页面来获得相关
„ 信息,因为微软公司会为 CodeWarrior 的发行版本提供一些升级补丁。
„ 对于特定平台,比如Macintosh 的开发者可以使用 Metrowerks 自己的 PowerPlant 类库。
„ PowerPlant 是为编写 Mac 应用程序而设计的面向对象的应用程序框架。我们在本课程中并不打算讨
„ 论 PowerPlant,但你应知道,它与 MFC 在许多方面是类似的。你在这里学到的知识也将帮助你理
„ 解 PowerPlant。我们讨论 MFC 时,其中的许多概念也可以应用到 PowerPlant 上。
„ 注意: 在 Macintosh 版的 CodeWarrior 光盘中也有一个 MFC 的库文件,但不像
„ Windows 版的光盘,这里不包含源代码。使用 MFC,你可以编写跨平台的代码,还可
„ 以同时为 Macintosh(使用 PowerPlant) 和 PC(使用 MFC) 编译这个代码。是不是很酷?
„ 应用程序框架
„ 就像前面提到过的一样,MFC 是一个应用程序框架。也就是说,MFC 是一个源代码或库格式的
„ C++ 类集。使用这个框架可以在较短时间内创建一个支持高级操作系统功能的完整的应用程序。此
„ 外,MFC 还包含了用以构造你的用户界面的工具。这些工具,特别是图象编辑器、对话框编辑器和
„ 资源编译器,能够帮助你构造用户界面中的图形元素(在本课最后一节中将解释如何安装这些有用的
„ 组件)。一个应用程序框架只涉及到应用程序的标准用户界面,而与该应用程序的特有的内容无关。
„ 换句话说,这个框架能够帮助你构造一个功能强大的用户界面,把你的时间节省下来以便让你有更多
„ 时间去编写实现应用程序目的的其它函数。因此你不必担心会花很多时间来创建一个和其它一些运行
„ 在操作系统环境中具有同样 Windows 化界面的应用程序,因为你只需去运用那些库就可以达到这些
„ 目的了。
上海天马
第七章 库 和 Microsoft Foundation Classes (MFC)
上海天马
第七章 库 和 Microsoft Foundation Classes (MFC)

„ 应用程序框架还能处理分发消息(例如用户击键的动作、鼠标点击、绘画消息等等)到应用程序中的许多按
钮、列表、窗口和控件上。这个功能帮助你能够集中注意力到实现应用程序的功能而不是界面上,把那些
创建界面的工作留给应用程序框架吧。
„ 应用程序框架提供了许多超过老式风格的 roll-your-own 方法。首先,这些代码是成熟和经过严格测试的。
每天都有成百上千的开发者使用 MFC 来开发应用程序。每当 Windows 操作系统增加了一些新的功能的时
候,MFC 也会不断地被升级,你可以通过使用新版本的 MFC 来编译你的应用程序,以便获得所有新的功
能特色,而且几乎不用对应用程序的源代码做任何修改。
„ 应用程序框架还提供可重用的代码。代码重用是象 C++ 这样的面向对象的编程方法得以发展的主要原因
之一。通过将可重用的代码封装为类,你可以很容易地使用已经存在的类来添加需要的功能。
„ 代码重用使得你可以使用经过严格测试的代码来构造你的应用程序,并很容易获得预期的功能。而且你还
可以很容易地将你编写的类与其它需要同样功能的人进行共享。
„ 与你自己创建所需框架而言,使用应用程序框架有时会使得你的程序稍大一些。因为现代计算机通常都配
置了足够数量的内存,而且这个框架可以作为一个 DLL 来使用,所以增加这么一些程序体积还是很值得的。
PowerPlant 和 MFC 是两个很值得你去熟练使用的高效的工具。
„ 如何安装和使用 MFC 接口工具
„ MFC 接口工具(包括对话编辑器和图象编辑器)可以在 CodeWarrior 安装光盘上找到。但是,它们并不是作
为 CodeWarrior 安装程序的一部分存在的,因此在完成了 CodeWarrior 的安装后,在硬盘上你还是找不到
MFC。为了安装这些工具,请按照以下步骤进行:
„ 找到 iTOOLS.Exe 文件。这是安装 MFC 接口工具必须的安装程序。iTools.Exe 文件可以在
C:\Program\Files\Metrowerks\CodeWarrior\BinSDK\bin\ 目录下找到。如果在那儿找不到这个文件,那么
就到 CodeWarrior 的安装光盘上去找。该文件应该在 Extras\SKDs\Win32\Microsoft Win32 SDK Tools\目
录下。
„ 注意: 该安装文件 (iTOOLS.Exe) 将会询问你想在哪里保存 MFC 接口工具。但不行的是,它却没有提供定
位目录用的浏览(browser)按钮可用,因此你必须手工的输入一个路径。如果你并不能确定你输入的路径是
否就是你想要保存这些工具的路径,你可以先在那个目录中找到一个文件,然后通过查看该文件的属性(在
该文件上点击右键然后选择Properties 项),从这个属性框上你可以复制到完整的路径,并把它填入到安装
过程中提示要输入安装路径的编辑框中。
„ 图 7-1 MFC 的用户界面构造器
上海天马
第七章 库 和 Microsoft Foundation Classes (MFC)

„ 这些工具将要被安装到目的安装路径的 \bin\ 目录中。在这个路径中你将可以找


到对话框编辑器(DlgEdit.Exe),图象编辑器(ImagEdit.Exe)和其它一些有用的工
具;
„ 如果你正在开发 Windows 95 或 Windows NT,需要的工具可以在 \bin\win95
和 \bin\winnt目录中找到。

You might also like