《DEVC工程、预处理和EGG图形.ppt》由会员分享,可在线阅读,更多相关《DEVC工程、预处理和EGG图形.ppt(87页珍藏版)》请在金锄头文库上搜索。
1、 工程、预处理和工程、预处理和EGG库库 提纲提纲1.使用工程组织多个源文件使用工程组织多个源文件2.预处理命令预处理命令3.Egg图形库说明图形库说明 2.模块化和工程模块化和工程模块的定义模块的定义一般把用一个名字就可调用的一段程序称为一般把用一个名字就可调用的一段程序称为“模块模块”,如子程序、函数等。,如子程序、函数等。模块的基本属性:模块的基本属性:n功能:描述该模块实现什么功能功能:描述该模块实现什么功能n逻辑:描述模块内部怎么做逻辑:描述模块内部怎么做n状态:该模块使用时的环境和条件状态:该模块使用时的环境和条件除了基本属性,还需描述模块的内部和外部特性除了基本属性,还需描述模块
2、的内部和外部特性n模块的外部特性:模块的模块名、参数表模块的外部特性:模块的模块名、参数表n模块的内部特性:完成其功能的程序代码和仅供该模块的内部特性:完成其功能的程序代码和仅供该模块内部使用的数据模块内部使用的数据n通常是先确定模块的外部特性,再确定其内部特性。通常是先确定模块的外部特性,再确定其内部特性。 1.使用工程组织多个源文件使用工程组织多个源文件函数是最小的模块,若干个紧密相关的函数可函数是最小的模块,若干个紧密相关的函数可以组成更大的模块源文件。以组成更大的模块源文件。一条好的原则就是保持模块的紧凑性即在同一条好的原则就是保持模块的紧凑性即在同一个源文件中只包含那些在逻辑上与其相
3、关的一个源文件中只包含那些在逻辑上与其相关的函数。函数。 1.使用工程组织多个源文件使用工程组织多个源文件模块化:把程序划分成独立命名且可独立访问的模块,模块化:把程序划分成独立命名且可独立访问的模块,每个模块完成一个子功能,所有模块集成起来构成的每个模块完成一个子功能,所有模块集成起来构成的整体可完成用户的所有需求。整体可完成用户的所有需求。模块化意义模块化意义n降低了系统的复杂性,使系统容易修改和重用;降低了系统的复杂性,使系统容易修改和重用;n推动系统各部分的并行开发,提高开发效率。推动系统各部分的并行开发,提高开发效率。复杂问题复杂问题较小问题较小问题高层模块高层模块从整体上把握问题从
4、整体上把握问题,隐蔽细节隐蔽细节分解分解 1.使用工程组织多个源文件使用工程组织多个源文件使用工程来组织多个源文件。使用工程来组织多个源文件。将功能紧密相关的若干个函数组成单独的源文将功能紧密相关的若干个函数组成单独的源文件。件。对应于每一个提供通用功能的源文件,建立头对应于每一个提供通用功能的源文件,建立头文件。文件。#include“ListNode.h”自定义的头文件,自定义的头文件,该文件在工程所在目录下该文件在工程所在目录下#include“E:/temp/MyType.h“自定义的自定义的头文件,该文件不在工程所在目录下头文件,该文件不在工程所在目录下#include标准库函数头文
5、件标准库函数头文件 1.使用工程组织多个源文件使用工程组织多个源文件实例:猴子选大王实例:猴子选大王源文件的分割源文件的分割头文件的使用头文件的使用使用工程组织多个源文件使用工程组织多个源文件 在DEV-C+集成开发环境中:1.创建工程文件创建工程文件(.dev) 文件/新建/工程,在弹出窗口中选择Console Application2、往项目中增加源文件往项目中增加源文件(.c) 工程/新建单元 新建一个源文件加到项目中或者 工程/添加 将已有的一个源文件加到项目中3、编译、链接、运行,查看结果、编译、链接、运行,查看结果 运行/编译 编译项目中所有源文件 或者运行/编译当前文件 编译当前
6、源文件或者运行/编译运行编译项目中所有源文件、链接、运行DEV-C+下工程的创建 一一.新建工程新建工程1.点击菜单:文件点击菜单:文件-新建新建-工程工程.DEV-C+下工程的创建 2.在弹出窗口的在弹出窗口的Basic页中选择页中选择ConsoleApplication,输入工程名称,选择是,输入工程名称,选择是c工程,点击确定。工程,点击确定。DEV-C+下工程的创建 3.此时弹出对话框,要求指定工程存放路径(如此时弹出对话框,要求指定工程存放路径(如G:temptestProject)。选择好路径后点击保存。)。选择好路径后点击保存。DEV-C+下工程的创建 4.此时系统自动加入此时系
7、统自动加入main.c文件如下。里面代码文件如下。里面代码是系统自动是系统自动生成的。生成的。DEV-C+下工程的创建 二. 往工程中增加已创建的其他文件往工程中增加已创建的其他文件将将linkNode.h、link.c和和link.h三个文件拷贝到三个文件拷贝到工程所在目录工程所在目录G:temptestProject下下然后点击菜单然后点击菜单工程工程-添加添加DEV-C+下工程的创建 在弹出的对话框中选择要添加的源文件。然后点击打开。在弹出的对话框中选择要添加的源文件。然后点击打开。DEV-C+下工程的创建 此时在工程管理(此时在工程管理(Project)页中出现了加入这)页中出现了加入
8、这3个文件个文件DEV-C+下工程的创建 在工程管理页中鼠标左键点击在工程管理页中鼠标左键点击link.c,则右边的代码区出现该,则右边的代码区出现该文件的源代码。文件的源代码。DEV-C+下工程的创建 DEV-C+下工程的创建保存保存main.c在右边的代码区选择在右边的代码区选择main.c,然后然后Ctrl+S进行保进行保存,此时弹出对话框,询问保存的目录。存,此时弹出对话框,询问保存的目录。 三三.编译文件编译文件若选择编译若选择编译(CtrlF9),则编译当前工程中的,则编译当前工程中的所有文件。若只是想单独编译一个文件,则选所有文件。若只是想单独编译一个文件,则选择择编译当前文件编
9、译当前文件(Shift+CtrlF9)。DEV-C+下工程的创建 DEV-C+下工程的创建编译成功后,在工程所在目录编译成功后,在工程所在目录G:temptestProject中包含文件如下中包含文件如下双击双击.exe即可运行程序。即可运行程序。也可使用也可使用Execute菜单下的菜单下的Run菜单运行程序。菜单运行程序。.dev是工程文件。双击该文件即可在是工程文件。双击该文件即可在DevC+环境中打环境中打开工程。开工程。 四、在当前工程中新建一个文件四、在当前工程中新建一个文件如果要新建文件并将其添加到工程中,则选择如果要新建文件并将其添加到工程中,则选择菜单菜单工程工程-新建单元新
10、建单元DEV-C+下工程的创建 此时将加入一个文件(未命名此时将加入一个文件(未命名3)。选择保存时,指定该文件的)。选择保存时,指定该文件的名字和保存路径(一般和工程在同一路径下)。如下图所示名字和保存路径(一般和工程在同一路径下)。如下图所示DEV-C+下工程的创建 五五.从工程中移除一个文件。从工程中移除一个文件。如下图所示。注意:此时该文件在磁盘里还是如下图所示。注意:此时该文件在磁盘里还是存在,只是不包含在当前工程中了。存在,只是不包含在当前工程中了。DEV-C+下工程的创建 DEV-C+下工程的创建注意:添加一个已存在的文件到工程中时,该文件也可注意:添加一个已存在的文件到工程中时
11、,该文件也可以不位于工程所在路径下。假设工程位于以不位于工程所在路径下。假设工程位于D:tempproject目录下,要加入工程的目录下,要加入工程的linkNode.h、link.h和和link.c位于其他目录,则编译后工程所在目录位于其他目录,则编译后工程所在目录如下,并没有将上述三个文件复制到工程目录下(其如下,并没有将上述三个文件复制到工程目录下(其时在文件时在文件.dev中记录着上述中记录着上述3个文件的磁盘路径)个文件的磁盘路径) 在VC6开发环境中:1.点击点击File-New弹出菜单(如下图)弹出菜单(如下图)VC6环境下工程的创建 2.选择选择Projects选项卡,选择选项
12、卡,选择Win32ConsoleApplication,在,在Projectname文本框输入工程名(如文本框输入工程名(如elevator),在),在Location文本框选择路径文本框选择路径如(如如(如C:test)(见下图)点击)(见下图)点击OKVC6环境下工程的创建 3.点击Finish(如下图)VC6环境下工程的创建 4.点击点击OK(如下图)(如下图)VC6环境下工程的创建 5.把所有源文件 例elevator.c、elevator.h文件拷贝到工程所在目录下(如C:TEST) 。VC6环境下工程的创建 6.点击左下角的点击左下角的FileView(如下图红色圈所示),再鼠标右
13、键点击(如下图红色圈所示),再鼠标右键点击SourceFiles(如下图红色箭头所示),(如下图红色箭头所示),选择选择AddFilestoFolder,选择文件将,选择文件将elevator.c加入到加入到SourceFiles目目录,录,鼠标右键点击鼠标右键点击HeaderFiles,选择,选择AddFilestoFolder,选择文件将,选择文件将elevator.h加入到加入到HeaderFiles目录(结果如下图)目录(结果如下图)VC6环境下工程的创建 7.选择主菜单选择主菜单Project-Settings(工程(工程-设置)出对话框(如下图)设置)出对话框(如下图)VC6环境下
14、工程的创建 VC6环境下工程的创建8.点击左边树状导航栏点击左边树状导航栏elevator,点击右边选项卡,点击右边选项卡Link,找到找到Object/librarymodules:文本框,在最后添加两项文本框,在最后添加两项Msimg32.lib、egg.lib(如图)点击(如图)点击OK 9.这样就可以编写自己的主程序了,比如在这样就可以编写自己的主程序了,比如在SourceFile目录下建立目录下建立main.c文件,文件,main.c应包含应包含前面的前面的elevator.h(如下图如下图)VC6环境下工程的创建 提纲提纲1.使用工程组织多个源文件使用工程组织多个源文件2.预处理命
15、令预处理命令3.Egg图形库说明图形库说明 预处理指令预处理指令#include预处理指令预处理指令#define:符号常量符号常量预处理指令预处理指令#define:宏:宏条件编译条件编译提纲提纲 预处理指令预处理指令#define:宏:宏#define用来定义用来定义符号常量(用符号表示的常量)符号常量(用符号表示的常量)。宏(用符号定义的操作)。宏(用符号定义的操作)。宏宏宏用来替代一个字符串,类似于符号常量,宏用来替代一个字符串,类似于符号常量,宏在预处理时被替换字符串取代。宏在预处理时被替换字符串取代。不带参数的宏:预处理程序就像处理符号常不带参数的宏:预处理程序就像处理符号常量一样
16、处理不带参数的宏。量一样处理不带参数的宏。带参数的宏:先用替换文本取代参数,然后带参数的宏:先用替换文本取代参数,然后再把宏展开。再把宏展开。 预处理指令预处理指令#define:宏:宏带参数的宏定义格式:带参数的宏定义格式:#define标识符标识符(形式参数表形式参数表)字符串字符串形式参数表由逗号分割开的标识符组成,这些形式参数表由逗号分割开的标识符组成,这些标识符在字符串中出现。标识符在字符串中出现。如:如:#definePI3.14159/常量定义常量定义#defineCIRCLE_AREA(x)(PI*(x)*(x)#defineMAX(x,y)(x)(y)?(x):(y)#def
17、ineNUL(x,y)(x)*(y) 预处理指令预处理指令#define:宏:宏宏调用格式:宏调用格式:标识符(实在参数表)标识符(实在参数表)如:如:area=CIRCLE_AREA(3+4);宏在预处理时被展开:宏在预处理时被展开:1.替换参数替换参数:文件中如果出现宏调用文件中如果出现宏调用CIRCLE_AREA(3+4),则字符串中的,则字符串中的x都用都用3+4替替代代;2.用字符串取代程序中的宏调用。用字符串取代程序中的宏调用。语句语句area=CIRCLE_AREA(3+4);在预处理;在预处理时将被展开成时将被展开成area=(3.14159*(3+4)*(3+4);(3.14
18、159*(3+4)*(3+4)预处理时被展开预处理时被展开 预处理指令预处理指令#define:宏:宏需要注意的是,需要注意的是,在宏名和括起参数的括号之间在宏名和括起参数的括号之间绝对不能有空格绝对不能有空格。此外,为了避免在翻译宏时。此外,为了避免在翻译宏时产生歧义,产生歧义,宏体和参数也应该用括号括起来宏体和参数也应该用括号括起来。例如,象下例中这样定义宏例如,象下例中这样定义宏CIRCLE_AREA是是不正确的:不正确的:defineCIRCLE_AREA(x)PI*x*x如:如:inta=3,b=4;语句语句area=CIRCLE_AREA(a+b);将被展开成将被展开成3.1415
19、9*a+b*a+b; 预处理指令预处理指令#define:宏:宏使用宏还是函数使用宏还是函数宏与函数相比有一个明显的优势,即它比函宏与函数相比有一个明显的优势,即它比函数效率更高数效率更高(并且更快并且更快),因为宏可以直接在,因为宏可以直接在源代码中展开,而调用函数还需要额外的开源代码中展开,而调用函数还需要额外的开销。销。但是,宏一般比较小,无法处理大的、复杂但是,宏一般比较小,无法处理大的、复杂的代码结构,而函数可以。的代码结构,而函数可以。此外,宏需要逐行展开,因此宏每出现一次,此外,宏需要逐行展开,因此宏每出现一次,宏的代码就要复制一次,这样你的程序就会宏的代码就要复制一次,这样你的
20、程序就会变大,而使用函数不会使程序变大。变大,而使用函数不会使程序变大。 条件编译条件编译使编译器能够按照不同条件编译不同的程序使编译器能够按照不同条件编译不同的程序部分,产生不同的目标代码文件。部分,产生不同的目标代码文件。两种条件编译:使用常量表达式判断、使用两种条件编译:使用常量表达式判断、使用宏定义名判断宏定义名判断条件编译条件编译 条件编译条件编译1.使用常量表达式判断使用常量表达式判断(共共3种种)#if整型常量表达整型常量表达式式文本文本1#else其他文本其他文本#endif#if整型常量表达整型常量表达式式文本文本1#endif第第1种情况种情况第第2种情况种情况首先求常量表
21、达式的值,然后根据常量表达式值是否为首先求常量表达式的值,然后根据常量表达式值是否为0进行进行下面的条件编译。在第下面的条件编译。在第2种情况中,如果该表达式的值非种情况中,如果该表达式的值非0,则编译文本则编译文本1,否则编译其他文本。,否则编译其他文本。#if整型常量表达式整型常量表达式1文本文本1#elif整型常量表达式整型常量表达式2文本文本2#else其他文本其他文本#endif第第3种情况种情况 条件编译条件编译让编译器不编译某一段代码:让编译器不编译某一段代码:#if0不编译的代码不编译的代码#endif以后若想让编译器编译该段代码,只需要将以后若想让编译器编译该段代码,只需要将
22、0改改成成1 条件编译条件编译2.使用宏定义名判断使用宏定义名判断#ifdef标识符标识符文本文本1#else文本文本2#endif#ifndef标识符标识符文本文本1#endif如果定义了标识符为宏(即使宏体为空),则为真,如果定义了标识符为宏(即使宏体为空),则为真,编译编译#ifdef后面的文本;否则编译后面的文本;否则编译#else后面的文本后面的文本#ifdef标识符标识符文本文本1#endif 条件编译条件编译#ifdef标识符是标识符是#ifdefine(标识符)的缩写(标识符)的缩写#ifndef标识符是标识符是#if!define(标识符)的(标识符)的缩写缩写 条件编译条件
23、编译调试阶段调试阶段,若想打印变量的值,则代码如下:,若想打印变量的值,则代码如下:#defineDEBUG/定义宏,宏体为空定义宏,宏体为空#ifdefDEBUGprintf(“variablex=%dn”,x);printf(“variabley=%dn”,y);#endif完成调试后,可以去掉完成调试后,可以去掉#define指令,这样就会指令,这样就会在编译过程中忽略上述两条在编译过程中忽略上述两条printf语句。语句。 条件编译条件编译#include#defineDEBUG/定义宏定义宏main()intage;charname20;printf(inputyouragen);s
24、canf(%d,&age);printf(inputyournamen);scanf(%s,name); 条件编译条件编译#ifdefDEBUGprintf(inputageis:%dn,age);#endif#undefDEBUG/取消宏定义取消宏定义#ifdefDEBUGprintf(inputnameis:%sn,name);#endifsystem(pause);return0;inputyourage30inputyournamejohninputageis:30请按任意键继续请按任意键继续. 条件编译条件编译怎样避免多次包含同一个头文件怎样避免多次包含同一个头文件?在创建一个头文件
25、时,你可以用在创建一个头文件时,你可以用#define指令为指令为它定义一个唯一的标识符名称。你可以通过它定义一个唯一的标识符名称。你可以通过#ifndef指令检查这个标识符名称是否已被定指令检查这个标识符名称是否已被定义,如果已被定义,则说明该头文件已经被包义,如果已被定义,则说明该头文件已经被包含了,就不要再次包含该头文件;反之,则定含了,就不要再次包含该头文件;反之,则定义这个标识符名称,以避免以后再次包含该头义这个标识符名称,以避免以后再次包含该头文件。文件。 猴子选大王猴子选大王NodeType.h:#ifndef_NODETYPE_H#define_NODETYPE_Hstruct
26、listNodeintdata;structlistNode*nextPtr;typedefstructlistNodeLISTNODE;typedefLISTNODE*LISTNODEPTR;#endif#include“NodeType.h”#include“NodeType.h”main.c编译遇到第编译遇到第1条条include指令,指令,由于由于_NODETYPE_H未被定义,未被定义,因此该头文件被包含,因此该头文件被包含,_NODETYPE_H被定义;编译遇被定义;编译遇到第到第2条条include指令时,由于指令时,由于_NODETYPE_H已定义,因此该已定义,因此该头文件将
27、不再被包含头文件将不再被包含 其他其他预处理指令预处理指令#error,#program运算符运算符#和和#行号行号#line预定义的符号常量预定义的符号常量宏宏assert 提纲提纲1.使用工程组织多个源文件使用工程组织多个源文件2.预处理命令预处理命令3.Egg图形库说明图形库说明 图形库函数EGG简介可以把代码编译成库供其他人员调用。其他人可以把代码编译成库供其他人员调用。其他人员看不到源代码。员看不到源代码。两种库:静态链接库和动态链接库两种库:静态链接库和动态链接库静态链接库静态链接库在链接(在链接(link)的时候被连接到)的时候被连接到.exe文件文件(.LIB中的代码被包含到中
28、的代码被包含到.exe文件中了),文件中了),导致应用程序比较大。导致应用程序比较大。当当.LIB版本升级时,需要对调用该版本升级时,需要对调用该LIB的程的程序重新编译。序重新编译。.exeLIB 图形库函数EGG简介.DLL(DynamicLinkLibrary):动态链接库动态链接库DLL是一个包含可由多个程序同时使用的是一个包含可由多个程序同时使用的代码和数据的库。例如,在代码和数据的库。例如,在Windows操作操作系统中,系统中,Comdlg32DLL执行与对话框有关执行与对话框有关的常见函数。因此,每个程序都可以使用该的常见函数。因此,每个程序都可以使用该DLL中包含的功能来实现
29、中包含的功能来实现“打开打开”对话框。对话框。事先不被连接到事先不被连接到.exe文件,在运行期才会被文件,在运行期才会被调用。调用。1.exeDLL调用调用调用调用2.exe 图形库函数图形库函数EGG简介简介动态链接库是分两步链接进程序中的动态链接库是分两步链接进程序中的:首先,在编绎的时候,链接器查找出程序需首先,在编绎的时候,链接器查找出程序需要的所有符号(函数,变量等等),然后链要的所有符号(函数,变量等等),然后链接进程序当中或者程序的另一个共享链接库接进程序当中或者程序的另一个共享链接库当中。当中。动态链接库中的目标文件并没有固化进可执动态链接库中的目标文件并没有固化进可执行文件
30、。替代的是,当程序运行的时候,由行文件。替代的是,当程序运行的时候,由系统的一个程序(叫做动态装载器系统的一个程序(叫做动态装载器dynamiclibraries)检查程序需要哪些动态链接库,)检查程序需要哪些动态链接库,然后把它们装入内存并且与内存中的程序关然后把它们装入内存并且与内存中的程序关联。联。 图形库函数图形库函数EGG简介简介DLL的优点的优点使用较少的资源使用较少的资源当多个程序使用同一个函数库时,当多个程序使用同一个函数库时,DLL可以减少在可以减少在磁盘和物理内存中加载的代码的重复量。这不仅可磁盘和物理内存中加载的代码的重复量。这不仅可以大大影响在前台运行的程序,而且可以大
31、大影响以大大影响在前台运行的程序,而且可以大大影响其他在其他在Windows操作系统上运行的程序。操作系统上运行的程序。推广模块式体系结构推广模块式体系结构DLL有助于促进模块式程序的开发。有助于促进模块式程序的开发。简化部署和安装简化部署和安装当当DLL中的函数需要更新或修复时,部署和安装中的函数需要更新或修复时,部署和安装DLL不要求重新建立程序与该不要求重新建立程序与该DLL的链接。此外,的链接。此外,如果多个程序使用同一个如果多个程序使用同一个DLL,那么多个程序都将,那么多个程序都将从该更新或修复中获益。当您使用定期更新或修复从该更新或修复中获益。当您使用定期更新或修复的第三方的第三
32、方DLL时,此问题可能会更频繁地出现。时,此问题可能会更频繁地出现。 图形库函数EGG简介Egg提供提供2个静态链接库和个静态链接库和1个头文件:个头文件:egg.lib/静态链接库静态链接库eggd.lib/静态链接库静态链接库egg.h 图形库函数图形库函数EGG简介简介EGG绘图功能:绘图功能:绘制直线绘制直线绘制曲线(正圆和椭圆)绘制曲线(正圆和椭圆)绘制字符串绘制字符串贴图:贴图:.bmp文件文件设置画笔的颜色和线条粗细设置画笔的颜色和线条粗细移动画面的某些部分(动画)移动画面的某些部分(动画) 图形库函数图形库函数EGG简介简介坐标系统坐标系统采用我们最熟悉的平面采用我们最熟悉的平
33、面直角坐标系,左下角是直角坐标系,左下角是坐标原点,坐标原点,X坐标向右坐标向右递增,递增,Y坐标向上递增,坐标向上递增,单位是厘米单位是厘米坐标原坐标原点点 图形库函数图形库函数EGG简介简介画笔当前位置画笔当前位置在在Egg中有一个画笔,尽管我们看不到它,中有一个画笔,尽管我们看不到它,但它确确实实存在。画笔指向位置的坐标就但它确确实实存在。画笔指向位置的坐标就是画笔的当前位置,简称画笔位置。所有绘是画笔的当前位置,简称画笔位置。所有绘图操作都是从画笔位置开始落笔绘图,按照图操作都是从画笔位置开始落笔绘图,按照绘图要求移动画笔,并把最后提笔结束的位绘图要求移动画笔,并把最后提笔结束的位置作
34、为新的画笔位置。置作为新的画笔位置。画笔的初始位置是画面的左上角画笔的初始位置是画面的左上角,并非坐标原点(左下角)。,并非坐标原点(左下角)。画笔初画笔初始位置始位置 画笔相关函数画笔相关函数voidMovePen (double x, double y)移移动画笔位置到新的画笔位置到新的绝对坐坐标voidOffsetPen(double dx, double dy)按相按相对当前位置的位移移当前位置的位移移动画笔位移画笔位置画笔位移画笔位置doubleGetPenXPos (void)得到画笔的得到画笔的X坐坐标doubleGetPenYPos (void)得到画笔的得到画笔的Y坐坐标 图
35、形库函数图形库函数EGG简介简介初始化初始化只要调用一个函数只要调用一个函数EggStart()就完就完成所有初始化成所有初始化Egg平台的工作。平台的工作。voidEggStart(doublefWidth,doublefHeight);参数:绘图窗口的宽和高,单位厘米。参数:绘图窗口的宽和高,单位厘米。你不需要考虑你不需要考虑Egg的结束问题。只要程序正的结束问题。只要程序正常退出,常退出,Egg占用的所有资源都会被自动释占用的所有资源都会被自动释放。放。 图形库函数图形库函数EGG简介简介直线直线voidDrawLine(doubledx,doubledy)从画笔当前位置,按照参数指定的
36、位移画一从画笔当前位置,按照参数指定的位移画一条直线。条直线。位移可以为正(沿位移可以为正(沿X/Y坐标的正方向绘制)、坐标的正方向绘制)、也可为负也可为负(沿沿X/Y坐标的负方向绘制)坐标的负方向绘制)voidline(void)EggStart(5,5);/初始化初始化DrawLine(5,-5);/绘制直线绘制直线WaitForExit();/等待用户关闭窗口等待用户关闭窗口 图形库函数图形库函数EGG简介简介正圆曲线正圆曲线voidDrawArc(doubler,doubledStart,doubledSweep);r:曲线所在圆的半径,单位厘米。:曲线所在圆的半径,单位厘米。dSta
37、rt:曲线开始点在圆周上的角度(即画:曲线开始点在圆周上的角度(即画笔在圆周上的角度)笔在圆周上的角度)dSweep:曲线沿圆周按逆时针方向扫过的:曲线沿圆周按逆时针方向扫过的角度。角度。DrawArc(2,45,90); 图形库函数图形库函数EGG简介简介DrawArc(2,45,90);圆半径为圆半径为2的圆可以有多个,但是画笔位置在圆周上的圆可以有多个,但是画笔位置在圆周上角度为角度为45的圆只有一个。画笔位置、圆半径以及角度的圆只有一个。画笔位置、圆半径以及角度唯一确定一个圆。唯一确定一个圆。 voidyuan1(void)EggStart(4,4);OffsetPen(4,-2);/
38、相对移动相对移动DrawArc(2,0,360);WaitForExit();voidyuan1(void)EggStart(4,4);OffsetPen(4,-1);/相对移动相对移动DrawArc(2,0,360);WaitForExit(); voidyuan1(void)EggStart(4,4);OffsetPen(2,-2);/相对移动相对移动DrawArc(2,0,360);WaitForExit(); 图形库函数图形库函数EGG简介简介椭圆曲线椭圆曲线voidDrawEllipticalArc(doublerx,doublery,doubledStart,doubledSwee
39、p);参数参数dStart和和dSweep的含义与的含义与DrawArc完全完全相同。相同。rx是该椭圆在是该椭圆在x轴的半径,轴的半径,ry是在是在Y轴轴的半径。的半径。 图形库函数图形库函数EGG简介简介字符串字符串voidDrawString(char*pString);例如,要输出例如,要输出HelloWorld,使用如下代,使用如下代码:码:DrawString(HelloWorld);字符串的左上角位于当前的画笔位置,输出字符串的左上角位于当前的画笔位置,输出后画笔位置移动到字符串的右上角。后画笔位置移动到字符串的右上角。 HelloWorld 图形库函数图形库函数EGG简介简介贴
40、图贴图Egg支持支持.bmp文件的贴图,使用下面函数:文件的贴图,使用下面函数:voidDrawBitmap(char*lpszFilename);参数是参数是bmp文件名,例如要贴当前目录下的文件名,例如要贴当前目录下的“beauty.bmp”文件,可以使用下面语句:文件,可以使用下面语句:DrawBitmap(beauty.bmp);位图的左上角位于画笔当前位置,贴图后,位图的左上角位于画笔当前位置,贴图后,画笔当前位置移动到位图的右上角。画笔当前位置移动到位图的右上角。 图片图片 voidyuan1(void)EggStart(4,4);OffsetPen(2,-2);DrawArc(2
41、,0,360);MovePen(2,2);DrawString(hello);DrawBitmap(pic.bmp);WaitForExit(); 图形库函数图形库函数EGG简介简介画笔颜色和宽度画笔颜色和宽度函数函数SetPen()改变画笔的颜色和宽度,从此改变画笔的颜色和宽度,从此都用指定的颜色和宽度绘画各种图形、文字,都用指定的颜色和宽度绘画各种图形、文字,直到下次调用相关函数为止。直到下次调用相关函数为止。voidSetPen(unsignedlongcolor,doublefWidth);fWidth是宽度,单位厘米。是宽度,单位厘米。color是颜色,取值见具是颜色,取值见具体宏定
42、义。体宏定义。如果只想单独改变颜色或宽度,可以调用如果只想单独改变颜色或宽度,可以调用voidSetPenColor(unsignedlongcolor)voidSetPenWidth(doublefWidth) 动画实现动画实现盘子:白色窗口盘子:白色窗口egg:任何图形都是画在一个:任何图形都是画在一个egg上,每个上,每个egg都都是相对独立的,可以绘画、移动任何一个是相对独立的,可以绘画、移动任何一个egg,而不会影响其它的而不会影响其它的egg。只能以。只能以egg为单位进行为单位进行移动。移动。egg的大小与调用的大小与调用EggStart()时指定的大小一致,时指定的大小一致,并
43、且覆盖整个盘子(盘子是并且覆盖整个盘子(盘子是Egg图形窗口的昵图形窗口的昵称),但它初始状态是透明的。称),但它初始状态是透明的。 可以画多个可以画多个egg,当两个蛋重合,后下,当两个蛋重合,后下的蛋会覆盖先下的蛋。使用的蛋会覆盖先下的蛋。使用ChangeEggLayer()可以改变可以改变egg的层次,调整互相之间的层次,调整互相之间的覆盖关系。的覆盖关系。 如何下蛋:如何下蛋:每次调用每次调用LayEgg()都会生成一个新的都会生成一个新的egg,并把这个并把这个egg的句柄返回给你。的句柄返回给你。HEGGLayEgg(void);执行完执行完EggStart()后,便已经偷偷建立了
44、一后,便已经偷偷建立了一个个egg,所有的绘图操作,都是在这个,所有的绘图操作,都是在这个egg上上进行的。当进行的。当LayEgg()后,再执行绘图操作,后,再执行绘图操作,就是在新的就是在新的egg上绘图了。上绘图了。 如何设置活动蛋:如何设置活动蛋:绘图是在活动蛋上进行的;绘图是在活动蛋上进行的;如果想回头在旧如果想回头在旧egg上绘图,可以使用上绘图,可以使用voidSetActiveEgg(HEGGhEgg)函数函数将旧的将旧的egg变成活动蛋变成活动蛋因此,需要把每次因此,需要把每次LayEgg()的返回值(的返回值(egg的句柄)保存下来,从而将旧蛋变成活动蛋;的句柄)保存下来,
45、从而将旧蛋变成活动蛋; #includeegg.h#defineNUMBER_OF_EGG5intmain(void)HEGGhEggsNUMBER_OF_EGG;inti;EggStart(10,5);for(i=0;iNUMBER_OF_EGG;i+)hEggsi=LayEgg();DrawArc(i+1,180,180);WaitForExit();/等待用户关闭窗口等待用户关闭窗口 return0; 如何动蛋如何动蛋voidMoveEgg(doublex,doubley);voidOffsetEgg(doubledx,doubledy);这里的这里的(x,y)是是egg左上角在盘子内的
46、坐标,左上角在盘子内的坐标,(dx,dy)是在盘子坐标系内的位移。是在盘子坐标系内的位移。需要特别注意的是,在需要特别注意的是,在egg上绘画时,所采上绘画时,所采用的坐标系是每个用的坐标系是每个egg自己的独立坐标,而自己的独立坐标,而不是盘子坐标。也就是说,绘画时,不需要不是盘子坐标。也就是说,绘画时,不需要考虑考虑egg在盘子内的位置,在盘子内的位置,egg自己的左下角自己的左下角永远是坐标原点。永远是坐标原点。 /画画5个能分别动起来的半圆个能分别动起来的半圆voiddonghua1(void)HEGGhEggsNUMBER_OF_EGG;inti;EggStart(10,5);/画画
47、5个不同半径的半圆个不同半径的半圆for(i=0;iNUMBER_OF_EGG;i+)hEggsi=LayEgg();DrawArc(i+1,180,180); /让让5个半圆分别移动个半圆分别移动i=0;while(WaitFor(100)SetActiveEgg(hEggsi);OffsetEgg(NUMBER_OF_EGG-i-1)*0.1,0);if(iNUMBER_OF_EGG-1)i+;elsei=0; /画画5个能个能同时同时动起来的半圆动起来的半圆voiddonghua2(void)HEGGhEggsNUMBER_OF_EGG;inti;EggStart(10,5);SetAu
48、toUpdate(0);/设置不自动更新屏幕设置不自动更新屏幕 for(i=0;iNUMBER_OF_EGG;i+)hEggsi=LayEgg();DrawArc(i+1,180,180); Update();/也可以不要也可以不要i=0;while(WaitFor(100)/定时器定时器SetActiveEgg(hEggsi);OffsetEgg(NUMBER_OF_EGG-i-1)*0.1,0);if(iNUMBER_OF_EGG-1)i+;elsei=0;Update();/更新更新Egg窗口,窗口,将将5个个egg的分时移动的分时移动模拟模拟为为同时动同时动 第第8周实验周实验1)掌握
49、)掌握VC6下工程的下工程的管理管理。2)掌握图形库)掌握图形库Egg的库函数使用。的库函数使用。 移动的是当前的活动蛋(移动的是当前的活动蛋(activeegg),该蛋上),该蛋上所有的图形都会一起动。所有的图形都会一起动。如果只是想动整个图形的一部分(如电梯、小如果只是想动整个图形的一部分(如电梯、小火车),则该部分一定要在一个独立的火车),则该部分一定要在一个独立的egg上上绘制。绘制。移动一个移动一个egg之前,需要先通过函数之前,需要先通过函数voidSetActiveEgg (HEGGhEgg)将该将该egg设置为活动蛋。设置为活动蛋。 4.3-Egg定时器1intWaitFor(
50、unsignedintuMillisecond);这是一种很简单的定时器。调用此函数后,你的程序在这是一种很简单的定时器。调用此函数后,你的程序在uMillisecond毫秒内将什么也不做,静静地等待毫秒内将什么也不做,静静地等待WaitFor()函数的函数的返回。在需要延时的场合,这个函数是很好用的。但当用户关闭返回。在需要延时的场合,这个函数是很好用的。但当用户关闭窗口的时候,它会立即返回,返回值为窗口的时候,它会立即返回,返回值为0。此时,我们要停止正在。此时,我们要停止正在做的事情,转入退出流程。做的事情,转入退出流程。 例:例:/让让5个个egg分别移动分别移动#include“eg
51、g.h”/先定义先定义5个个eggi=0; while(WaitFor(100)SetActiveEgg(hEggsi);OffsetEgg(NUMBER_OF_EGG-i-1)*0.1,0);if(iNUMBER_OF_EGG-1)i+;elsei=0; 4.4-Egg定时器2voidStartTimer(unsignedintuMillisecond);voidStopTimer(void);这两个函数比这两个函数比WaitFor()稍微复杂一点儿,但它稍微复杂一点儿,但它们的控制能力更精准,而且可以和其它输入完们的控制能力更精准,而且可以和其它输入完全配合(全配合(WaitFor()在等
52、待的时候,用户的所有在等待的时候,用户的所有输入动作都无效,除了关闭窗口)。输入动作都无效,除了关闭窗口)。StartTimer()后,每隔后,每隔uMillisecond毫秒,都会毫秒,都会产生一个产生一个TIMER事件,可以用事件,可以用WaitForEvent()得到这个事件,进而做相应的周期工作。不再得到这个事件,进而做相应的周期工作。不再需要定时事件时,调用需要定时事件时,调用StopTimer()停止它。停止它。 4.4-Egg定时器2EVENT_TYPEev;.StartTimer(500);while(ev=WaitForEvent()!=EXIT)switch(ev)caseTIMER:/响应周期事件响应周期事件break;caseKEYDOWN:/响应按键按下事件响应按键按下事件break;caseKEYUP:/响应按键抬起事件响应按键抬起事件break;StopTimer(); 建议:定时器函数可以用在动画建议:定时器函数可以用在动画输出部分,控制对电梯画面的刷输出部分,控制对电梯画面的刷新。新。