4.1 图形状态显示原理
Turbo C 2.0 默认显示方式为文本方式,这种显示方式就是平时看到的情况。但是图形方 式和文本方式不同,在图形方式下可以画图,它的显示单位是像素。显示器显示的图形是由一 些圆点组成的(其亮度、颜色不同),这些点被称为像素。满屏显示像素多少,则决定了显示 的分辨率高低,可以看出像素越小(或个数越多),则显示的分辨率越高。像素在屏幕上的位 置则由其所在的(x,y)坐标值决定。
显示屏的图形坐标系统就像一个倒置的直角坐标系,如图 4-1 所示。
图 4-1 图形绝对坐标系统
定义屏幕的左上角为原点,正 x 轴向右延伸,正 y 轴向下延伸,即(x,y)坐标值均为 非负整数,但它的最大值则由显示器的类型和显示方式来决定,即显示的像素大小可以通过设 置不同的显示方式来改变。比如在图 4-1 所示的显示方式下,(x,y)最大坐标分别是(639,
399),即满屏显示的像素个数为 640×400,则称这种相对屏幕显示的坐标叫物理坐标或绝对 坐标。还有一种坐标叫相对坐标,它的参照物是图视窗口。图视窗口就是指在物理坐标区间又 开辟一个或多个区间,在这些区间又可定义一个相对坐标系统,这样以后画图均可在此区间进 行,并以相对坐标来定义位置。例如,在图 4-1 所示的显示方式下定义了一个左上角坐标为
(200,50),右下角坐标为(400,150)的一个区域为图视窗口,则以后处理图形时,就以其 左上角为坐标原点(0,0),右下角为坐标(200,100)的坐标系来定位图形上各点位置。
Turbo C 2.0 为用户提供了一个功能很强的画图软件库,它又被称为 Borland 图形接口
(BGI),它包括图形库文件(graphics.lib)、图形头文件(graphics.h)和许多图形显示器(图 形终端)的驱动程序。还有一些字符集的字体驱动程序。编写图形程序时用到的一些图形库函 数均在 graphics.lib 中,执行这些函数时,所需的有关信息(如宏定义等)则包含在 graphics.h 头文件中。因此用户在自己的画图源程序中必须包括 graphics.h 头文件,在进行目标程序连接 时,要将 graphics.lib 连接到自己的目标程序中去。
由于计算机画图涉及显示器和驱动它们工作的图形适配器(卡)等许多硬件知识,因此 在这里有必要简单地介绍一下。
(0,0)
(0,479) (639,479)
(639,0)
x
y
4.1.1 图形适配器
计算机中显示的字符和图形均以数字形式存储在存储器中,而显示器接收的是模拟信号。
插在 PC 插槽中的图形卡的作用就是将要显示的字符和图形以数字形式存储在卡上的视频存储 器 VRAM 中,再将其变成视频模拟信号送往相应适配的显示器显示,这表明适配器在计算机 主机和显示器之间起到了信息转换和视频发送作用,但是由于显示器种类不同,因而适配器种 类也就不同,同样不同适配器又可支持不同的分辨率显示方式、文本显示方式和颜色设置。因 此不同的适配器导致了不同的图形模式,其中常用的适配器主要有下面 3 种:
(1)彩色图形适配器(CGA)。
这是 PC/XT 等微机配用的图形卡,它可以产生单色或彩色字符和图形。在图形方式下,
Turbo C 2.0 支持两种分辨率供选择:一种为高分辨方式(CGAHI),像素数为 640×200,这时 背景色是黑的(当然也可重新设置),前景色可供选择,但前景色只是同一种,因而图形只显 示两色;另一种为中分辨显示方式,像素数为 320×200,其背景色和前景色均可由用户选择,
但仅能显示 4 种颜色。在该显示方式下,有 4 种模式供选择,即 CGAC0、CGACl、CGAC2 及 CGAC3,它们的区别是显示的 4 种颜色不同。
(2)增强型图形适配器(EGA)。
该适配器除支持 CGA 的 4 种显示模式外,还增加了 Turbo C 2.0 称为 EGALO(EGA 低 分辨显示方式,分辨率为 640×200)的 16 色显示方式,和 640×350 的 EGAHI(EGA 高分 辨显示方式,分辨率为 640×350)的 16 色显示方式。
(3)视频图形阵列适配器(VGA)。
它支持 CGA 和 EGA 的所有显示方式,但自己还有 640×480 的高分辨显示方式
(VGAHI)、640×350 的中分辨显示方式(VGAMED)和 640×200 的低分辨显示方式
(VGALO),它们均可有 16 种显示颜色可供选择。
由于众多生产厂家推出了许多性能优于 VGA 但名字各异的图形显示系统,美国标准协会 为此制定了主要性能标准,常将属于这类的显示适配卡统称为 SVGA。目前基本上使用的都 是属于 SVGA,它也可以使用 VGA 卡方式进行编程。
4.1.2 显示器工作方式
显示器有两种工作方式,即文本显示方式和图形显示方式。它们的主要差别是选择文本方 式时,VRAM 存放要显示字符的 ASCII 码值,并用它作为地址,然后取出字符发生器 ROM(固 定存储器)中存放的相应字符的图像(又称字模),变成视频信号在显示器屏上进行显示。EGA、
VGA 可以使用几种字符集,如 EGA 下有 3 种字符集,VGA 有 5 种字符集。而当选择图形方 式时,则要显示的图形的图像直接存在 VRAM 中,VRAM 中某地址单元存放的数就表示了相 应屏幕上某行和列上的像素及颜色。例如,在 CGA 的中分辨图形方式下,每字节代表 4 个像 素,即每 2 位表示一个像素及颜色。
4.1.3 图形系统的初始化与关闭
在进入图形方式前,首先要在程序中对使用的图形系统进行初始化,即要选择采用什么 类型的适配器驱动程序,采用什么模式的图形方式,以及该适配器驱动程序的寻找路径名。注 意所用系统的适配器一定要支持所选用的显示模式;否则将出错。当图形系统初始化后,才可
以进行画图操作。
1.图形系统初始化函数
Turbo C 2.0 提供的 initgraph 函数可完成图形系统初始化的功能。其原型是:
void far initgraph(int far *driver,int far *mode,char far *path_for_driver);
当使用的存储模式为 tiny(微型)、small(小型)或 medium(中型)时,不需要远指针,
因而可以将初始化函数的调用格式改成以下形式:
initgraph(&driver,&mode,"");
其中驱动程序目录路径为空字符" "时,表示在当前目录下,参数 mode 的用法如表 4-1 所示。
表 4-1 参数 mode 对应表
适配器 Driver 模式 Mode 分辨率 颜色数 页数 标识符
0 320×200 4 1 CGA0
1 320×200 4 1 CGA1
2 320×200 4 1 CGA2
3 320×200 4 1 CGA3
CGA
4 640×200 2 1 CGHI
0 640×200 16 4 EGAL0
EGA 1 640×350 16 2 EGAHI
0 640×200 16 1 EGA64L0
EGA64
1 640×350 4 1 EGA64HI
EGAMONO 0 640×350 2 1 EGAMONOHI
0 640×200 16 2 VGAL0
1 640×350 16 2 VGAMED
VGA
2 640×480 16 1 EGAHI
0 320×200 4 1 MCGA0
1 320×200 4 1 MCGA1
2 320×200 4 1 MCGA2
3 320×200 4 1 MCGA3
4 640×200 2 1 MCGAMED
MCGA
5 640×280 2 1 MCGAHI
HREC 0 720×348 2 1 HRECMONOH
0 320×200 4 1 ATT4000
2 320×200 4 1 ATT4001
3 320×200 4 1 ATT4002
4 320×200 4 1 ATT4003
5 640×200 2 1 ATT400MED
ATT400
5 640×400 2 1 ATT400HI
PC3270 0 720×350 2 1 PC3270HI
0 640×480 25
IBM8514
1 1024×768 6
参数 driver 是一个枚举变量,它属于显示器驱动程序的枚举类型:
enum driver {DETECT,CGA,MCGA,EGA,EGA64,EGAMONO,IBM 8514,HERCMONO, ATT400,VGA,PC3270};
其中枚举成员的值顺序为:DETECT 为 0,CGA 为 1,依次类推。当不知道所用显示适配 器名称时,可将 driver 设成 DETECT,它将自动检测所用显示适配器类型,并将相应的驱动 程序装入系统,将其最高显示模式作为当前显示模式,如表 4-2 所示。
表 4-2 不同适配器的显示模式
检测到的适配器 选中的显示模式
CGA 4(640×200,2 色,即 CGAHI)
EGA 1(640×350,16 色,即 EGAHI)
VGA 2(640×480,16 色,即 VGAHI)
例 4-1 下面是一般画图程序的开始部分,它包括对图形系统的初始化。
#include <graphics.h>
main()
{ int driver=DETECT;
int mode;
initgraph(&driver,&mode,"");
… }
在本例初始化过程中,先由 DETECT 检测所用适配器类型,并将当前目录下相应的驱动 程序装入系统,并采用最高分辨率显示模式作为 mode 的值。
若已知所用图形适配器为 VGA 时,想采用 640×480 的高分辨显示模式 VGAHI,则图形 初始化部分可改写为:
int driver=VGA;
int mode=VGAHI;
initgraph(&driver,&mode," ");
2.图形系统检测函数
当 driver=DETECT 时,实际上 initgraph 函数又调用了图形系统检测函数 detectgraph,由 它来完成对适配器的检查,并得到显示器类型号和相应的最高分辨率模式,若所设适配器不是 规定的那些类型,则返回-2,表示适配器不存在,该函数的原型是:
void far detectgraph(int far *graphdriver,int far *graphmode);
3.清屏和恢复显示方式的函数
画图前要清除屏幕,因此必须使用清屏函数。清屏函数的原型是:
void far cleardevice(void);
该函数作用范围为整个屏幕,如果用函数 setviewport 定义一个图视窗口,则可采用清除 图视窗口函数,它仅清除图视窗口区域内的内容,该函数的原型是:
void far clearviewport(void);
当画图程序结束后,系统要回到文本方式,这时应该关闭图形系统,关闭图形系统的函数 原型是:
void far closegraph(void);
由于进入 Turbo C 2.0 环境编程时,即已经进入文本方式,因而为了在画图程序结束后恢
复原来的最初状况,一般在画图程序结束前调用该函数,使其恢复到文本方式。另外,为了不 关闭图形系统,使相应适配器的驱动程序和字符集(字库)仍驻留在内存,但系统又返回到原 来所设置的模式下,就可用恢复工作模式函数进行清屏操作,它的原型是:
void far restorecrtmode(void);
该函数常和另一设置图形工作模式函数 setgraphmode 交互使用,使得显示器工作方式在 图形和文本方式之间来回切换,这在编制菜单程序和说明程序时很有用处。
4.2 基本绘图方法
4.2.1 基本绘图函数
由于图形是由点、线、面 3 个成分组成的,因此 Turbo C 2.0 提供了一些函数来实现这些 操作,其中所谓的面可由对封闭图形填色来实现。当图形系统初始化后,要进行的画图操作均 可采用默认值作为参数的当前值。
1.画点函数
void far putpixel(int x,int y,int color);该函数表示在指定的(x,y)处画一点,点的颜色由 设置的 color 值来决定,关于颜色的设置,将在设置颜色函数中介绍。
int far getpixel(int x,int y);该函数与 putpixel()相对应,它得到在(x,y)点位置上的像素的 当前颜色值。
2.有关坐标位置的函数
void far moveto(int x,int y);该函数移动画笔到指定的(x,y)位置,移动过程不画点。
void far moverel(int dx,int dy);该函数从现行位置(x,y)移到一位置增量处(x+dx,y+dx), 移动过程不画点。
int far getx(void);得到当前画笔的 x 位置。
int far gety(void);得到当前画笔的 y 位置。
3.画线函数
这类函数提供了用设定的颜色从一个点到另一个点画一条直线的功能,由于起始点的设 定方法不同,因而有下面不同的画线函数:
void far line(int x0,int y0,int x1,int y1);该函数从(x0,y0)点到(x1,y1)点画一直线。
void far lineto(int x,int y);该函数从现行画笔位置到(x,y)点画一直线。
void far linerel(int dx,int dy);该函数从现行画笔位置(x,y)到位置增量处(x+dx,y+dy)
画一直线。
例 4-2 用 line 函数画直线时,将不考虑画笔位置,它也不影响画笔原来的位置,lineto 和 1inerel 要求画笔位置,画线起点从此位置开始,而结束位置就是画笔画线完后停留的位置,
故这两个函数将改变画笔的位置。
#include <graphics.h>
main()
{ int driver=VGA;
int mode=VGAHI;
initgraph(&driver,&mode," ");
cleardevice();
moveto(100,20);
lineto(100,80);
moveto(200,20);
lineto(100,80);
line(100,90,200,90);
linerel(0,20);
moverel(-100,0);
linerel(30,20);
getch();
closegraph();
}
4.画矩形和条形图函数
void far rectangle(int xl,int y1,int x2,int y2);该函数将以(x1,y1)为左上角,(x2,y2)为右 下角画一矩形框。
void bar(int x1,int y1,int x2,int y2);该函数将以(xl,y1)为左上角,(x2,y2)为右下角画一 实形条状图,没有边框,图的颜色和填充模式可以设定。若没有设定,则使用缺省模式。
void far drawpoly(int numpoints, int far *polypoints);该函数画一个顶点数为 numpoints,各 顶点坐标由 polypoints 给出的多边形。polypoints 整型数组必须至少有 2 倍顶点数个元素。每 一个顶点的坐标都定义为(x,y),并且 x 在之前。值得注意的是,当画一个封闭的多边形时,
numpoints 的值取实际多边形的顶点数加一,并且数组 polypoints 中第一个点和最后一个点的 坐标相同。
例 4-3 用 drawpoly()函数画箭头。
# include<graphics. h>
# include<conio.h>
main()
{ int gdriver, gmode, i;
int arw[16]={200, 102, 300, 102, 300, 107, 330,100, 300, 93, 300, 98, 200, 98, 200, 102};
gdriver=DETECT;
initgraph(&gdriver, &gmode, "");
setbkcolor(BLUE);
cleardevice();
setcolor(12); /*设置作图颜色*/
drawpoly(8, arw); /*画一箭头*/
getch();
closegraph();
}
例 4-4 下面的程序将由 rectangle 函数以(100,20)为左上角,(200,50)为右下角画一 矩形,接着又由 bar 函数以(100,80)为左上角,(150,180)为右下角画一实形条状图,用 缺省颜色(白色)填充。
# include <graphics.h>
main()
{ int driver=DETECT;
int mode, x;
initgraph(&driver,&mode,” ”);
cleardevice();
rectangle(100,20,200,50);
bar(100,80,150,180);
getch();
closegraph();
}
5.画椭圆、圆和扇形图函数
有关于角的概念,在 Turbo C 2.0 中是这样规定的:屏的 x 轴方向为 0°,当半径从此处逆 时针方向旋转时,则依次是 90°、180°、270°,到 360°时,则和 x 轴正向重合,即旋转了一周,
如图 4-2 所示。
图 4-2 角的概念
void ellipse(int x,int y,int stangle,int endangel,int xradius,int yradius);该函数将以(x,y)为中 心,以 xradius 和 yradius 为 x 轴和 y 轴半径,从起始角 stangle 开始到 endangle 角结束,画一 椭圆线。当 stangle=0,endangle=360 时,则画出的是一个完整的椭圆,否则画出的将是椭圆 弧。关于起始角和终止角规定如图 4-2 所示。
void far circle(int x,int y,int radius);该函数将以(x,y)为圆心,radius 为半径画个圆。
void far arc(int x,int y,int stangle,int endangle,int radius);该函数将以(x,y)为圆心,radius 为半径,从 stangle 为起始角开始,到 endangle 为结束角画一圆弧。
void far pieslice(int x,int y,int stangle,int endangle,int radius);该函数将以(x,y)为圆心,radius 为半径,从 stangle 为起始角,endangle 为结束角,画一扇形图,扇形图的填充模式和填充颜 色可以事先设定,否则以缺省模式进行。
例 4-5 该程序将用 ellipse 函数画椭圆,从中心为(320,100),起始角为 0°,终止角为 360°,x 轴半径为 75,y 轴半径为 50 画一椭圆,接着用 circle 函数以(320,220)为圆心,
以半径为 50 画圆。然后分别用 pieslice 和 ellipse 及 arc 函数在下方画出了一扇形图和椭圆 弧及圆弧。
#include <graphics.h>
main()
{ int driver=DETECT;
int mode,x;
initgraph(&driver,&mode," ");
cleardevice();
ellipse(320,100,0,360,75,50);
circle(320,220,50);
pieslice(320,340,30,150,50);
ellipse(320,400,0,180,100,35);
起始角=0 结束角=
arc(320,400,180,360,50);
getch();
closegraph();
}
4.2.2 颜色设置函数
在 Turbo C 2.0 中,像素的显示颜色,或者说画点、画线、填充面的颜色既可采用默认值,
也可用一些函数来设置。图形方式下,像素有前景色和背景色之分,一般用以下的两个函数来 设置前景色和背景色:
void far setbkcolor( int color);设置背景色。
void far setcolor(int color);设置前景(作图)色。
其中 color 为图形模式下颜色的规定数值,对 EGA、VGA 显示器的适配器来说,有关颜 色的符号常数及数值如表 4-3 所示。
表 4-3 景色值与对应的颜色名
色值 颜色名 颜色 色值 颜色名 颜色
0 BLACK 黑 8 DARKGRAY 深灰
1 BLUE 蓝 9 LIGHTBLUE 淡蓝
2 GREEN 绿 10 LIGHTGREEN 淡绿
3 CYAN 青 11 LIGHTCYAN 淡青
4 RED 红 12 LIGHTRED 淡红
5 MAGENTA 洋红 13 LIGHTMAGENTA 淡洋红
6 BROWN 棕 14 YELLOW 黄
7 LIGHTGRAY 浅灰 15 WHITE 白
例 4-6 Turbo C 2.0 还提供了几个获得现行像素颜色设置情况的函数。
int far getbkcolor(void);返回现行背景颜色值。
int far getcolor(void);返回现行作图颜色值。
int far getmaxcolor(void);返回最高可用的颜色值。
# include<graphics. h>
# include<conio.h>
main()
{ int driver, mode, i;
driver=DETECT;
registerbgidriver(EGAVGA_DRIVER); /*建立独立图形运行程序*/
initgraph(&driver, &mode", ""); /*图形初始化*/
setbkcolor(0); /*设置图形背景*/
cleardevice();
for(i=0; i<=15; i++)
{ setcolor(i); /*设置不同作图色*/
circle(320, 240, 20+i*10); /*画半径不同的圆*/
delay(1000); /*延迟 1000 毫秒*/
}
for(i=0; i<=15; i++)
{ setbkcolor(i); /*设置不同背景色*/
cleardevice();
circle(320, 240, 20+i*10);
delay(1000);
}
closegraph();
}
4.2.3 颜色控制函数
表 4-3 显示的只是一般情况下屏幕背景颜色的符号表,其实按照 CGA、EGA、VGA 图形 适配器的硬件结构,颜色是可以通过对其内部相应的寄存器进行编程来改变的。
为了形象地说明颜色的设置,一般用所谓调色板来进行描述,它实际上对应着一些硬件 的寄存器。从 C 语言的角度来看,调色板就是一张颜色索引表。
对 CGA 显示器,在中分辨显示方式下,有 4 种显示模式,每一种模式对应有一个调色 板,可用调色板号区别。每个调色板有 4 种颜色可以选择,颜色可以用颜色值 0、1、2、3 来 进行选择,由于 CGA 有 4 个调色板,一旦显示模式确定后,调色板即确定,如选 CGAC0 模 式,则选 0 号调色板,但选调色板的哪种颜色则可由用户根据需要从 0、1、2 和 3 中进行选择,
表 4-4 就列出了调色板与其对应的颜色值。其中若选调色板的颜色值为 0,表示此时选择的颜 色和当时的背景色一样。
表 4-4 CGA 的调色板号与对应的颜色值
模式 调色板号 颜色值
0 1 2 3
CGAC0 0 背景色 绿 红 黄
CGAC1 1 背景色 青 洋红 白
CGAC2 2 背景色 淡绿 淡红 棕
CGAC3 3 背景色 淡青 淡洋红 淡灰
对 EGA 显示器,其调色板也是一个颜色索引表,它存有 16 种颜色,经过组合变换最终 可以产生 64 种颜色,因此就可以通过对其内部相应的寄存器进行编程来改变这 16 种颜色。
EGA 图形系统初始化时,16 个调色板寄存器已装入确定的颜色,它们也被称为标准色。
VGA 显示器,也只有一个调色板,对应 16 个调色板寄存器。但这些寄存器装的内容和 EGA 的不同,它们装的又是一个颜色寄存器表的索引。经过组合变换最终 256 个颜色寄存器 供索引。由于 Turbo C 2.0 中没有支持 VGA 的 256 色的图形模式,因此 EGA 和 VGA 的调色 板寄存器装的值虽然一样(当图形系统初始化时,指默认值),但含义不同,前者装的是颜色 值,后者装的是颜色寄存器索引号,不过它们最终表示的颜色是一致的。
voidfar setpalette(int index, int actual_color);该函数用来对调色板进行颜色设置,一般用在 EGA、VGA 显示方式上。
void far setallpalette(struct palettetype far *palette);改变调色板 16 种颜色的函数。
void far getpalette(struct palettetype far *palette); 将得到调色板的颜色数(即调色板寄存器 个数)和装的颜色值。
void far getpalettesize(void);将得出调色板颜色数,同时 getpalette 函数将把得到信息存入 由 palette 指向的结构中。
结构 palettetype 定义如下:
#define MAXCOLORS l5 struct palettetype { unsigned char size;
signed char colors[MAXCOLORS+1];
};
该定义在头文件 graphics.h 中。size 元素由适配器类型和当前模式下调色板的颜色数决定,
即调色板寄存器数。colors 是个数组,它实际上代表调色板寄存器,每个数组元素的值就表示 相应调色板寄存器的颜色值。对 VGA 的 VGAHI 模式,size=16,默认的 colors 的各元素值就 相当于表 4-5 所列值。
表 4-5 6 个调色板寄存器对应的标准色和值
寄存器号 颜色名 值 寄存器号 颜色名 值
0 EGA_BLACK 0 8 EGA_DARKGRAY 8
1 EGA_BLUE 1 9 EGA_LIGHTBLUE 9
2 EGA_GREEN 2 10 EGA_LIGHTGREEN 10
3 EGA_CYAN 3 11 EGA_LIGHTCYAN 11
4 EGA_RED 4 12 EGA_LIGHTRED 12
5 EGA_MAGENTA 5 13 EGA_LIGHTMAGENTA 13
6 EGA_BROWN 6 14 EGA_YELLOW 14
7 EGA_LIGHTGRAY 7 15 EGA_WHITE 15
例 4-7 下面的一个程序演示了调色板颜色设置函数的作用,首先程序用 setcolor(1)设置 了前景颜色,其中参数 1 表示用 1 号调色板寄存器中的颜色,即默认值为蓝色,这样用 rectangle 将画出一个蓝色的方框,然后按任一键,这时用 setpalette(1,i)函数将分别设置 1 号调色板寄 存器为绿、青、红、黄、亮白。每按一键,方框颜色改变一次,直到方框变成亮白为止。因为 调色板相应的调色板寄存器所装的颜色一旦改变,用 setcolor(调色板寄存器号)设置的颜色 也立即改变。
该程序中将 palette 定义成 palettetype 类型结构,palettetype 结构如前所述,在 graphics.h 头文件中已有定义,这样用 getpalette(&pallette)函数得到图形系统初始化的各调色板寄存器的 颜色值(即默认值),然后在程序快结束时,用 setallpalette(&palette)恢复各调色板寄存器的原 来值。
#include <graphics.h>
main()
{ int driver=DETECT,mode;
struct palettetype palette;
int i,j;
initgraph(&driver,&mode,"");
getpalette(&palette);
setcolor(1);
rectangle(200,200,300,320);
getch();
i=2;
j=2;
do
{ printf("color=%d", j);
setpalette(1,i);
getch();
i++;
j++;
if(i= =6) i=20 ; if(i= =21) i=7 ; if(i= =8) i=56;
} while (j<16);
getch();
setallpalette(&palette);
closegraph();
}
4.2.4 画线的线型函数 1.设定线型函数
void far setlinestyle(int linestyle,unsigned upattern,int thickness);
当线的宽度参数(thickness)不设定时,取默认值,即一个像素宽,当设定为 3 时,可 取 3 像素宽,取值如表 4-6 所示。当线型参数(linestyle)不设定时,取默认值,即实线;设 定时,可有 5 种选择,如表 4-7 所示。upattern 参数只有在 1inestyle 取 4 或 USERBIT_LINE 时 才有意义,即表示在用户自定义线型时,该参数才有用。该参数若表示成 16 位二进制数,则 每位代表一个像素。是 1 的位,代表的像素用前景色显示;是 0 的位,代表的像素用背景色显 示(实际没有显示)。
表 4-6 线宽(thickness)
符号名 值 含义
NORM_WIDTH 1 1 个像素宽
THICK_WIDTH 3 3 个像素宽
表 4-7 直线的形状(linestyle)
符号名 值 含义
SOLID_LINE 0 实线
DOTTED_LINE 1 点线
CENTER_LINE 2 中心线
DASHED_LINE 3 点画线
USERBIT_LINE 4 用户自定义线
例 4-8 画线。
#include <graphics.h>
main()
{ int driver=VGA, mode =VGAHI;
int i,j,x1,y1,x2,y2;
initgraph(&driver,&mode," "), setbkcolor(EGA_BLUE);
cleardevice();
setcolor(EGA_GREEN);
circle(320,240,98); /*画出一个绿色圆 */
j=0;
setcolor(12); /*设置颜色为淡红色 */
for(i=0;i<=90;i=i+6) {
setlinestyle(0,0,j); /*画出一个套一个的矩形框 */
x1=440-i; y1=280-i;
x2=440+i; y2=280+i;
rectangle(x1,y1,x2,y2);
j=j+3;
if(j>4) j=0;
} j=0;
for ( i=0;i<=180;i=i+16) /*画出屏幕中心的 4 种线型的 4 色线 */
{ if(j>3)j=0;
setcolor(j+2);
setlinestyle(j,0,3);
j++;
x1=0; y1=i, x2=640; y2=480-i;
line(x1,y1,x2,y2);
}
setcolor(EGA_WHITE);
setlinestyle(4,0x1001,1); /*用户定义线型,1 个像素宽 */
line(220,240,420,240); /*画出通过圆心的 y 线 */
line(320,140,320,340); /*画出通过圆心的 x 线 */
getch();
closegraph();
}
2.得到当前画线信息的函数
void far getlinesettings(struct linesettingstype far *lineinfo);
该函数将把当前有关线的信息存放到由 lineinfo 指向的结构中,linesettingstype 结构定义 如下:
structlinesettingstype { int linestyle;
unsigned upattern;
int thickness;
};
4.2.5 封闭图形的填色函数及有关画图函数 1.填色函数
void far setfillstyle(int pattern,int color);
该函数将用设定的 color 颜色和 pattern 图模式对后面画出的轮廓图进行填充,这些图轮 廓是由待定函数画出的,color 实际上就是调色板寄存器索引号,对 VGAHI 方式为 0~15,即 16 色,pattern 表示填充模式,可用表 4-8 中的值或符号名表示。
表 4-8 填充模式(pattern)的规定
符号名 值 含义
EMPTY_FILL 0 用背景色填充
SOLID_FILL 1 用单色实填充
LINE_FILL 2 用“一”线填充
LTSLASH_FILL 3 用“∥”线填充
SLASH_FILL 4 用粗“∥”线填充
BKSLASH_FILL 5 用“\\”线填充
LTBKSLASH_FILL 6 用粗“\\”线填充
HATCH_FILL 7 用方网格线填充
XHATCH_FILL 8 用斜网格线填充
INTTERLEAVE_FILL 9 用间隔点填充
WIDE_DOT_FILL 10 用稀疏点填充
CLOSE_DOT_FILL 11 用密集点填充
USER_FILL 12 用用户定义样式填充
当 pattern 选用 USER_FILL 用户自定义样式填充时,setfillstyle 函数对填充的模式和颜色 不起任何作用,若要选用 USER_FILL 样式填充时,可选用下面的函数。
2.用户自定义填充函数
void far setfillpattern(char *upattern,int color);
该函数设置用户自定义可填充模式,以 color 指出的颜色对封闭图形进行填充。这里的 color 实际上就是调色板寄存器号,也可用颜色名代替。参数 upattern 是一个指向 8 个字节存 储区的指针,这 8 个字节表示了一个 8×8 像素点阵组成的填充图模,它是由用户自定义的,
它将用来对封闭图形填充。8 个字节的图模是这样形成的:每个字节代表一行,而每个字节的 每一个二进制位代表该行的对应列上的像素。是 1 则用 color 显示,是 0 则不显示。
例 4-9 下面的程序演示了如何用 setfillstyle(SOLID_FILL,color)对用 bar 生成的条状图 进行填充。对 VGA 显示器,由于可显示 16 色,因而通过 getpalette(&palette)函数,可得出 palette,
size 为 16。这样 for 循环,将使得用 bar 函数生成的 16 个小条分别填充上调色板上的 16 种颜 色,其顺序为缺省时(即标准的)调色板各寄存器的顺序颜色。
do 循环又利用随机函数 random(palette.size)随机产生 0~palette.size 的整数,对调色板各 寄存器的颜色重新进行设置,这样一旦 setpalette 函数对某调色板寄存器进行了颜色的重新设 置,则代表相应号调色板寄存器的小条颜色立即变成新设的颜色。若随机遇到 random 产生一
个 0,则 setpalette 立即对 0 号调色板用第二次 random 产生的数进行颜色设置,因而此时整个 屏幕显示的背景色立即发生变化,颜色为第二次 random 产生的颜色。关于调色板的设置问题,
可参阅前面已介绍过的调色板设置函数。
#include <graphics.h>
#include <stdio.h>
#include <stdlib.h>
main()
{ int driver=DETECT,mode;
struct palettetype palette;
int color;
initgraph(&driver,&mode,"");
getpalette(&palette);
for (color=0; color<palette.size; color++ ) /*对 16 个小条用 16 种颜色填充*/
{ setfillstyle(SOLID_FILL,color);
bar(20*(color-1),0,20*color,20);
}
if(palette.size>1)
{ do /* 对调色板 16 种颜色重新进行设置*/
setpalette(random(palette.size), random(palette.size));
while (!kbhit() );
getch();
}
setallpalette(&palette);
closegraph();
}
例 4-10 下面的程序演示了用不同填充图模(pattern)对由 bar 和 pieslice 函数产生的条 状和扇形图进行颜色填充。运行程序,可以看出第 1 个 bar(0,0,100,100)产生的方条将由蓝色 的斜线填充,即以 LTSlASH_FILL(3)图模填充。接着将由红色的网格(HATCH_FILL,RED)
图模填充一个扇形。由于缺省时,前景颜色为白色,故该扇形将用白色边框画出,接着用户自 定义填充模式,因而用 bar(100,100,200,200)画出的方条,将用用户定义的图模(用字符数组 gray50[]表示的图模),用黄色进行填充。
#include <graphics.h>
main()
{ int driver=VGA,mode=VGAHI;
struct fillsettingstype save;
char savepattern[8];
char gray50[]={0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x81};
initgraph(&driver,&mode,"");
getfillsettings(&save); /* 得到初始化时填充模式*/
if(save.pattern != USER_FILL ) setfillstyle(3,BLUE);
bar(0,0,100,100);
setfillstyle(HATCH_FILL,RED);
pieslice(200,300,90,180,90);
setfillpattern(gray50,YELLOW); /* 设定用户自定义图模进行填充*/
bar(100,100,200,200);
if(save.pattern==USER_FILL) setfillpattern(savepattern,save.color);
else
setfillpattern(savepattern, save.color); /* 恢复原来的填充模式 */
getch();
closegraph();
}
3.得到填充模式和颜色的函数
void far fillsettings(struct fillsettingstype far *fillinfo);
它将得到当前的填充模式和颜色,这些信息存在结构指针变量 fillinfo 指出的结构中该结 构定义是:
struct fillsettingstype
{ int pattern; /*当前填充模式*/
int color; /*填充颜色*/
};
void far getfillpattern(char *upattern);
该函数将把用户自定义的填充模式和颜色存入由 upattern 指向的内存区域中。
4.与填充函数有关的作图函数
void far bar3d(int x1,int y1,int x2,int y2,int depth,int topflag);
该函数画三维立体直方图,当 topflag 非 0 时,画出三维顶,否则将不画出三维顶,depth 决定了三维直方图的长度。
viod far sector(int x,int y,int stangle,int endang1e,int xradius,int yradius);
该函数将以(x,y)为圆心,以 xradius 和 yradius 为 x 轴和 y 轴半径,从起始角 stangle 开始到 endangle 角结束,画一椭圆扇形图,并按设置的填充模式和颜色填充。当 stangle 为 0,endangle 为 360 时,则画出一完整的椭圆图。
void far fillellipse(int x,int y,int xradius,int yradius);
该函数将以(x,y)为圆心,以 xradius 和 yradius 为 x 轴和 y 轴半径,画一椭圆图,
并以设定或默认模式和颜色填充。
void far fillpoly(int numpoints,int far *polypoints);
该函数将画出一个顶点数为 numpoints,各顶点坐标由 polypoints 给出的多边形,也即边 数为 polypoints-1,当为一封闭图形时,numpoints 应为多边形的顶点数加 1,并且第一个顶 点坐标应和最后一个顶点的坐标相同。
例 4-11 下面程序用 bar3d 函数画出了一个立方图,并且画面用蓝色斜线填充,接着由 第二个 bar3d 函数又在相邻位置画出一个没有顶的三维图,画面用红色方格填充。该函数的 topflag=0。在屏幕下方,由 sector 函数画出了一个不完整的椭圆,并用绿色填充,可以看出 差 120°就是一个完整的椭圆了。在其相邻位置则是由 fillellipse 函数画出的一个椭圆,它用淡 红色填充,屏幕的右上半是由 fillpoly 函数画出的一个六边图形,被填以洋红色,由于最初顶 点坐标和最后一个顶点坐标相同(同为(420,20)),所以是一个封闭的图形。
#include <graphics.h>
main()
{ int driver=VGA,mode=VGAHI;
struct fillsettingstype save;
char savepattern[8];
int d[]={420,20,330,45,330,145,420,120,510,145,510,55,420,20};
initgraph(&driver,&mode,"");
getfillsettings(&save);
setfillstyle(3,BLUE);
bar3d(100,50,150,120,30,1);
setfillstyle(HATCH_FILL,RED);
bar3d(200,50,250,120,30,0);
setfillstyle(1,GREEN);
sector(200,300,0,250,100,40);
setfillstyle(1,LIGHTRED);
fillellipse(420,300,100,40);
setfillstyle(1,5);
fillpoly(7,d);
getch();
setfillstyle(save.pattern,save.color);
closegraph();
}
5.可对任意封闭图形填充的函数
前面介绍的填充函数,只能对由上述特定函数产生的图形进行颜色填充,对任意封闭图 形均可进行填充的还有一函数,其原型说明为:
void far floodfill(int x,int y,int border);
该函数将对一封闭图形进行填充,其颜色和模式将由设定的或默认的图模与颜色决定。
其中参数(x,y)为封闭图形中的任一点,border 是封闭图形的边框颜色。编程时该函数位 于画图形的函数之后,即要填充该图形。需要注意的是:
(1)若(x,y)点位于封闭图形边界上,该函数将不进行填充。
(2)若对不是封闭的图形进行填充,则会填到别的地方,即会溢出。
(3)若(x,y)点在封闭图形之外,将对封闭图形外进行填充。
(4)由参数 border 指出的颜色必须与封闭图形的轮廓线的颜色一致;否则会填到别的 地方去。
例 4-12 下面的程序首先用白色线画出一个长方体,并用设定的亮红色(LIGHTRED)
和实填充模式填充该长方体的正面,然后使用两个 floodfill 函数用同样的模式和颜色填充该 长方体能看得见的另两面,然后将画线颜色由 setcolor(LIGHTGREEN)设置为亮绿色,并由 setfillstyle 设置填充模式为棕色和用平直线填充,由于该函数对 rectangle 画出的矩形框不起 作用,所以并不执行填充,当画好矩形框后,其后的 floodfill 函数将完成对该矩形框的填充,
即以棕色的平直线进行填充。可以作实验,当将 floodfill 中的 x、y 参数设在被填图形框外 时,结果会将该框外的所有区域填充。当 floodfill 中的 border 指定的颜色和画图框的颜色不 符时,也会将颜色填到图外边去。
#include <graphics.h>
main()
{ int driver=VGA,mode=VGAHI;
initgraph(&driver,&mode,"");
setbkcolor(BLUE);
setcolor(WHITE); /* 用白色画线 */
setfillstyle(1,LIGHTRED); /* 设填充模式和颜色 */
bar3d(100,200,400,350,100,1); /* 画长方体并填正面*/
floodfill(450,300,WHITE); /* 填侧面 */
floodfill(250,150,WHITE); /* 填顶部 */
setcolor(LIGHTGREEN);
setfillstyle(2,BROWN);
rectangle(450,400,500,450); /* 画矩形 */
floodfill(470,420,LIGHTGREEN); /* 填矩形 */
getch();
closegraph();
}
4.2.6 图视窗口操作函数
在图形方式下可以在屏幕上某一区域设置一个窗口,这样以后的画图操作均在这个窗口 内进行,且使用的坐标以此窗口顶左上角为(0,0)作参考,而不再用物理屏幕坐标[屏左角 为(0,0)点]。在图视窗口内画的图形将显示出来,超出图视窗口的部分可以不让其显示出 来,也可以让其显示出来(不剪断)。
1.图视窗口设置函数
void far setviewport(int xl,int y1,int x2,int y2, clipflag);
其中,(x1,y1)为图视窗口的左上角坐标,(x2,y2)为所设置的图视窗口右下角坐标,
它们都是以原屏幕物理坐标为参考的。clipflag 参数若为非 0,则所画图形超出图视窗口的部 分将被切除而不显示出来。若 clipflag 为 0,则超出图视窗口的图形部分仍将显示出来。
2.图视窗口清除与取信息函数 void far clearviewport(void);
该函数将清除图视窗口内的图像。
void far getviewsettings(struct viewport type far *viewport);
该函数将取得当前设置的图视窗口的信息,它存于由结构 viewporttype 定义的结构变量 viewport 中,结构 viewporttype 定义如下:
struct viewporttype {int left,top,right,bottom;int clipflag;};
使用图视窗口设置函数 setviewport,可以在屏上设置不同的图视窗口,甚至部分可以重叠,
然而最近一次设置的窗口才是当前窗口,后面的图形操作都视为在此窗口中进行,其他窗口均 无效。若不清除那些窗口的内容,则它们仍在屏上保持,当要对它们处理时,可再一次设置那 个窗口一次,这样它就又变成当前窗口了。使用 setbkcolor 设置背景色时,对整个屏幕背景起 作用,它不能只改变图视窗口内的背景,在用 setcolor 设置前景色时,它对图视窗口内画图起 作用。若下一次设置那个图视窗口没有设置颜色,那么上次在另一图视窗口内设置的颜色在本 次设置的图视口内仍起作用。
例 4-13 下面程序首先用 setviewpon 函数设置了一个左上角为(0,0)、右下角为(639,
199)的图视窗口,并设置 clipflag 参数为 1,即超出图视窗口的图形将被切除,接着画了一个 方框和一个边与方框一边相切的圆,它将完整地显示出来。按任意键后,开一个图视窗口,用 棕色画了和第一个窗口相同的方框和圆,超出图视窗口的部分被剪切。由于在开此窗口前,没 有用 clearviewport()清除上次的窗口内容,所以上次画的洋红色的方框和圆仍保留,当再按任 一键后,调用了 clearviewport()函数,因而将窗口中的棕色方框和圆清除了。接着又建立了一
个图视窗口,该窗口(50,50,200,125)和最初窗口(0,0,639,199)有部分重合,因而重合部分 的内容将在当前窗口中显示出来。新画的方框和圆也显示出来(窗外部分内容仍保留),由于 选择了 clipflag=1,所以超出窗口的方框和圆的部分被剪切,不显示出来,但再按任一键后,
由于用了 clearviewport,所以窗口中内容被清除,并又在同一位置开辟了同样大小的窗口,但 由于 clipflag=0,所以超出的部分没被剪掉,因而可看见。
#include <graphics.h>
main()
{ int i,driver,mode,size,page;
driver=VGA;
mode=VGAHI;
initgraph(&driver,&mode," ");
cleardevice();
setviewport(0,0,639,199,1); /* 设图视窗口 */
setcolor(5);
rectangle(50,50,125,100);
circle(100,75,50);
getch();
setviewport(150,150,639,239,1); /* 又设一图视窗口 */
setcolor(6);
rectangle(50,50,125,100);
circle(100,75,50);
getch();
clearviewport(); /* 方框超出部分被切掉 */
setviewport(50,50,200,125,1);
rectangle(50,50,125,100);
circle(100,75,50);
getch();
clearviewport();
setviewport(50,50,200,125,0);
rectangle(50,50,125,100);
circle(100,75,50);
getch();
clearviewport(); /* 开窗口,超出部分不切除 */
closegraph();
}
4.2.7 图形方式下的文本输出函数
在图形模式下,只能用标准输出函数,如 printf()、puts()、putchar() 函数输出文本到屏幕。
除此之外,其他输出函数(如窗口输出函数)都不能使用,即使是可以输出的标准函数,也只 以前景色为白色,按 80 列、25 行的文本方式输出。
为此 C 语言另外提供了一些专门用于在图形显示模式下的文本输出函数。下面将分别进 行介绍。
1.文本输出函数
void far outtext(char far *textstring);
该函数在现行位置输出字符串指针 textstring 所指的文本。
void far outtextxy(int x, int y, char far *textstring);
该函数输出字符串指针 textstring 所指的文本在规定的(x,y)位置。其中 x 和 y 为像素 坐标。
说明:这两个函数都是输出字符串,但经常会遇到输出数值或其他类型的数据,此时就必 须使用格式化输出函数 sprintf()。
sprintf()函数的调用格式为:int sprintf(char *str, char *format, variable-list);它与 printf()函数 不同之处是将按格式化规定的内容写入 str 指向的字符串中,返回值等于写入的字符个数。
例如:sprintf(s, "your TOEFL score is %d", mark);
这里 s 应是字符串指针或数组,mark 为整型变量。
2.有关文本字体、字型和输出方式的设置
有关图形方式下的文本输出函数,可以通过 setcolor()函数设置输出文本的颜色。另外,
也可以改变文本字体大小以及选择是水平方向输出还是垂直方向输出。
void far settexjustify (int horiz, int vert);
该函数用于定位输出字符串。对使用 outtextxy (int x, int y, char far *str textstring) 函数所输 出的字符串;其中哪个点对应于定位坐标(x,y)在 Turbo C 2.0 中是有规定的。如果把一个 字符串看成一个长方形的图形,在水平方向显示时,字符串长方形按垂直方向可分为顶部,中 部和底部 3 个位置,水平方向可分为左、中、右 3 个位置,两者结合就有 9 个位置。
settextjustify()函数的第一个参数 horiz 指出水平方向 3 个位置中的一个,第二个参数 vert 指出垂直方向 3 个位置中的一个,二者就确定了其中一个位置。当规定了这个位置后,用 outtextxy()函数输出字符串时,字符串长方形的这个规定位置就对准函数中的(x,y)位置。
而对用 outtext()函数输出字符串时,这个规定的位置就位于现行游标的位置。有关参数 horiz 和 vert 的取值参见表 4-9。
表 4-9 数 horiz 和 vert 的取值
符号常数 数值 用于
LEFT_TEXT 0 水平
RIGHT_TEXT 2 水平
BOTTOM_TEXT 0 垂直
TOP_TEXT 2 垂直
CENTER_TEXT 1 水平或垂直
void far settextstyle(int font, int direction, int charsize);
该函数用来设置输出字符的字形(由 font 确定)、输出方向(由 direction 确定)和字符大 小(由 charsize 确定)等特性。C 语言对该函数中各个参数的规定见表 4-10 至表 4-12 所示。
表 4-10 font 的取值
符号常数 数值 含义
DEFAULT_FONT 0 8×8 点阵字(默认值)
TRIPLEX_FONT 1 3 倍笔画字体
SMALL_FONT 2 小号笔画字体
SANSSERIF_FONT 3 无衬线笔画字体
GOTHIC_FONT 4 黑体笔画字
表 4-11 irection 的取值
符号常数 数值 含义
HORIZ_DIR 0 从左到右
VERT_DIR 1 从底到顶
表 4-12 charsize 的取值
符号常数或数值 含义
1 8×8 点阵
2 16×16 点阵
3 24×24 点阵
4 32×32 点阵
5 40×40 点阵
6 48×48 点阵
7 56×56 点阵
8 64×64 点阵
9 72×72 点阵
10 80×80 点阵
USER_CHAR_SIZE=0 用户定义的字符大小
例 4-14 图形屏幕下文本输出和字体字型设置函数的用法。
# include<graphics.h>
main()
{ int i, driver, mode;
char s[30];
driver=DETECT;
initgraph(&driver, &mode, "");
setbkcolor(BLUE);
cleardevice();
setviewport(100, 100, 540, 380, 1); /*定义一个图形窗口*/
setfillstyle(1, 2); /*绿色以实填充*/
setcolor(YELLOW);
rectangle(0, 0, 439, 279);
floodfill(50, 50, 14);
setcolor(12);
settextstyle(1, 0, 8); /*三重笔画字体,水平放大 8 倍*/
outtextxy(20, 20, "Good Better");
setcolor(15);
settextstyle(3, 0, 5); /*无衬笔画字体,水平放大 5 倍*/
outtextxy(120, 120, "Good Better");
setcolor(14);
settextstyle(2, 0, 8);
i=620;
sprintf(s, "Your score is %d", i); /*将数字转化为字符串*/
outtextxy(30, 200, s); /*指定位置输出字符串*/
setcolor(1);
settextstyle(4, 0, 3);
outtextxy(70, 240, s);
getch();
closegraph();
}
3.用户对文本字符大小的设置
前面介绍的 settextstyle()函数,可以设定图形方式下输出文本字符的字体和大小,但对于 笔画型字体(除 8×8 点阵字以外的字体)只能在水平和垂直方向以相同的放大倍数放大。为 此 C 又提供了另一个 setusercharsize() 函数,对笔画字体可以分别设置水平和垂直方向的放大 倍数。该函数的调用格式为:
void far setusercharsize(int mulx, int divx, int muly, int divy);
该函数用来设置笔画型字和放大系数,它只有在 settextstyle() 函数中的 charsize 为 0(或 USER_CHAR_SIZE) 时才 起作用 ,并且 字体为 函数 settextstyle() 所规 定的字 体。 调用函 数 setusercharsize()后,每个显示在屏幕上的字符都以其缺省大小乘以 mulx/divx 为输出字符宽,
乘以 muly/divy 为输出字符高。
例 4-15 setusercharsize()函数的用法。
# include<graphics.h>
main()
{ int dirver, mode;
driver=DETETC;
initgraph(&driver, &mode, "");
setbkcolor(BLUE);
cleardevice();
setfillstyle(1, 2); /*设置填充方式*/
setcolor(WHITE); /*设置白色作图*/
rectangle(100, 100, 330, 380);
floodfill(50, 50, 14); /*填充方框以外的区域*/
setcolor(12); /*作图色为淡红*/
settextstyle(1, 0, 8); /*三重笔画字体,放大 8 倍*/
outtextxy(120, 120, "Very Good");
setusercharsize(2, 1, 4, 1); /*水平放大 2 倍,垂直放大 4 倍*/
setcolor(15);
settextstyle(3, 0, 5); /*无衬字笔画,放大 5 倍*/
outtextxy(220, 220, "Very Good");
setusercharsize(4, 1, 1, 1);
settextstyle(3, 0, 0);
outtextxy(180, 320, "Good");
getch();
closegraph() ; }
4.3 动画技术
大家知道电影或动画片是由一张张图像组成的,它利用人眼不能够分辨出时间间隔在 25 毫秒内的动态图像变化这一特性,在这些连续图像被放映时,从视觉效果上给人以动的感觉。
所以在计算机屏幕上产生运动的效果需要动画技术。
4.3.1 采用延迟与清屏交错的实现方法
这种方法利用 cleardevice()和 delay()函数相互配合,先画一幅图形,让它延迟一段时间,
然后清屏,再画另一幅,如此反复,就形成动态效果。
例 4-16 通过函数 graphone()、graphtwo()和 graphthree()实现了 3 个简单的动画画面,这 3 个画面不停地进行切换。
#include<graphics.h>
#include<stdlib.h>
#include<dos.h>
int x,y,maxcolor;
void graphone(char *str); /*使字符串 str 左右运动,线条上下运动*/
void graphtwo(char *str); /*使字符串 str 上下运动,线条左右运动*/
void graphthree(char *str); /*使字符串 str 由小变大,再由大变小,直线也随之变化*/
main()
{ int i,driver,mode;
char *str="W E L C O M E !";
driver=DETECT;
mode=0;
initgraph(&driver,&mode,""); /*系统初始化*/
cleardevice(); /*清屏*/
settextjustify(CENTER_TEXT,CENTER_TEXT);
x=getmaxx(); /* 返回当前图形模式下的最大有效的 x 值*/
y=getmaxy(); /* 返回当前图形模式下的最大有效的 y 值*/
maxcolor=getmaxcolor(); /* 返回当前图形模式下最大有效的颜色值*/
while(!kbhit())
{ graphone(str); /* 第一个动画*/
graphtwo(str); /* 第二个动画*/
graphthree(str); /* 第三个动画*/
} getch();
closegraph(); /* 关闭图形模式*/
}
void graphone(char *str) { int i;
for(i=0;i<40;i++) { setcolor(1);
settextstyle(1,0,4);
setlinestyle(0,0,3);
cleardevice();