1、cp03、预备知识0.1 开发平台: DosBox+Watcom C文档下载软件下载假定把上述压缩包解压到D:双击D:DosBoxWcwc.exe进入dosbox可以看到DosBox中显示的当前文件夹为c:watcomproject请注意此文件夹是虚拟的,实际对应的物理路径为:D:DosBoxWcwatcomproject0.2 如何编辑源程序?推荐使用第三方编辑器如editplus(下载链接: ),也可以用watcom C自带的vi编辑器。写好的程序应放在D:DosBoxWcwatcomproject内。0.3 如何编译?WCL386 hello.c0.4 如何运行?hello若错误信息太多
2、,可以打开hello.err查看。0.5 如何调试?调试前要对源程序重新编译,编译命令如下:WCL386 /d2 hello.c再输入调试命令:WD /tr=rsi hello调试按键:F10 step over 执行一步,不跟踪到函数内部F8 trace into 执行一步,跟踪到函数内部F4 user screen 观察程序的输出结果某行左侧的处点击鼠标可以设一个断点0.6 多个.c文件如何整合编译成一个.exe ?先建立1.c, 2.c再建立makefile,其内容如下:12.exe : 1.c 2.c wcl386 /fe=12.exe 1.c 2.c最后输入以下命令进行build:w
3、make一、坐标系统及graphics图形库中定义的全局变量二、 文本模式(text mode)编程指南DosBox刚运行时显卡的工作模式就是文本模式;要让显卡工作在图形模式的话,必须调用函数initgraph(); 若要从图形模式返回文本模式,则应该调用函数closegraph()或text_mode()或textmode(C80);例1:程序a.c在屏幕(0,0)处输出一个蓝色背景红色前景的字母A,在屏幕(1,0)处输出一个绿色背景白色前景的字母B。请注意,文本模式下,8位颜色值中的高4位为背景色,低4位为前景色,所以当设定蓝底红字时,颜色值应该等于(BLUE4)+RED = (14)+4
4、 = 0x14。例2:程序b.c输出2000个黑色背景红色前景的A。三、 图形模式(graphics mode)编程指南3.1 8bit图形模式1个点对应显存的1个字节,每个点最多有256种颜色变化。例3:程序c.c画一条红色水平线。#include #include main() int driver=0, mode=VESA_1024x768x8bit; char *p; int x=100, y=100, i; initgraph(&driver, &mode, ); p = _vp + y*_width + x; for(i=x; i600-x+1; i+) *p+ = RED; /
5、或写成 *p+ = 4; getchar();程序 c.c; (100,100)-(600,100)画一条红色水平线8bit图形模式下的颜色编号与颜色的对应关系(如4对应红色)与文本模式类似,具体请查阅头文件graphics.h中enum COLORS的定义或主页文档中的相关内容。例4:程序256color.c可以把全部256种颜色画出来:3.2 24bit图形模式1个点对应显存的3个字节,每个点的颜色有224种变化。以下示意图展示了VESA_1024x768x24bit模式下,如何在(0,0)处画了一个红点,在(x,y)处画一个青点:程序24bit0.c、24bit1.c、24bit2.c、
6、24bit3.c功能完全一样,都以(200,100)为左上角,以(400,300)为右下角画一个实心的青色矩形。但它们实现的过程有所不同。其中24bit3.c是最简单的,它直接调用bar()函数来画矩形;24bit2.c则是调用putpixel()函数画矩形中的每一个点;24bit1.c是通过语句pyx=c画矩形中的每一个点;24bit0.c是通过语句*p = (*p & 0xFF000000) | color;画矩形中的每一个点,上述语句的的执行过程可以用如下示意图描述:例5: 程序24bit0.c使用指针写显存画点,以(200,100)为左上角,以(400,300)为右下角画一个实心的青色
7、矩形。#include main() int driver=0, mode=VESA_1024x768x24bit; int x, y; long color = 0x0000FFFF; long *p; initgraph(&driver, &mode, ); for(y=100; y=300; y+) for(x=200; x=400; x+) p = (long *)(_vp + (y*_width+x) *(_color_bits/8); *p = (*p & 0xFF000000) | color; getchar(); closegraph(); 程序24bit0.c例6: 程序2
8、4bit1.c使用二维结构数组写显存画点,以(200,100)为左上角,以(400,300)为右下角画一个实心的青色矩形。#include typedef struct char blue; char green; char red; RGB;main() int driver=0, mode=VESA_1024x768x24bit; int x, y; RGB c = 0xFF, 0xFF, 0x00; RGB (*p)1024; initgraph(&driver, &mode, ); p = (RGB (*)1024) _vp; for(y=100; y=300; y+) for(x=2
9、00; x=400; x+) pyx = c; / 此语句相当于以下三句 /pyx.blue = c.blue; /pyx.green = c.green; /pyx.red = c.red; getchar(); closegraph(); 程序24bit1.c例7: 程序24bit2.c调用函数putpixel()画点,以(200,100)为左上角,以(400,300)为右下角画一个实心的青色矩形。#include main() int driver=0, mode=VESA_1024x768x24bit; int x, y; long color = 0x0000FFFF; initgr
10、aph(&driver, &mode, ); for(y=100; y=300; y+) for(x=200; x=400; x+) putpixel(x, y, color); / 调用画点函数 getchar(); closegraph(); 程序24bit2.c例8: 程序24bit3.c调用函数bar(),以(200,100)为左上角,以(400,300)为右下角画一个实心的青色矩形。#include main() int driver=0, mode=VESA_1024x768x24bit; long color = 0x0000FFFF; initgraph(&driver, &m
11、ode, ); /设定填充的模式及颜色setfillstyle(SOLID_FILL, color); bar(200, 100, 400, 300);/调用画实心矩形函数 getchar(); closegraph(); 程序24bit3.c3.3 32bit图形模式1个点对应显存的4个字节,每个点的颜色有224种变化。程序32bit.c也是以(200,100)为左上角,以(400,300)为右下角画一个实心的青色矩形。例9: 程序32bit.c在32bit图形模式下使用二维结构数组画点,以(200,100)为左上角,以(400,300)为右下角画一个实心的青色矩形。#include typ
12、edef struct char blue; char green; char red; char zero; RGB;main() int driver=0, mode=VESA_1024x768x32bit; int x, y; RGB c = 0xFF, 0xFF, 0x00, 0x00; RGB (*p)1024; initgraph(&driver, &mode, ); p = (RGB (*)1024) _vp; for(y=100; y=300; y+) for(x=200; x=400; x+) pyx = c; getchar(); closegraph(); 程序32bit
13、.c由于例9程序中的RGB结构成员的长度加起来刚好是4字节,因此完全可以用long类型来取代RGB结构,修改后的程序32bitx.c如下所示:例10: 程序32bitx.c在32bit图形模式下使用二维long型数组画点,以(200,100)为左上角,以(400,300)为右下角画一个实心的青色矩形。#include main() int driver=0, mode=VESA_1024x768x32bit; int x, y; long c = 0x0000FFFF; / red=0x00, green=0xFF, blue=0xFF long (*p)1024; initgraph(&dr
14、iver, &mode, ); p = (long (*)1024) _vp; for(y=100; y=300; y+) for(x=200; x=400; x+) pyx = c; getchar(); closegraph(); 程序32bitx.c四、图片输出4.1 显示8bit bmp图片调用函数load_8bit_bmp()可以在指定坐标位置显示一张256色bmp图片。例11: 程序8bitbmp.c调用函数load_8bit_bmp()在坐标(0,0)显示一张图片pic256.bmp,再在坐标(200,200)显示另一张图片hello.bmp。程序8bitbmp.c及配套图片文件
15、打包下载链接:#include #include main() int x, y; int driver=0, mode=VESA_1024x768x8bit; initgraph(&driver, &mode, ); load_8bit_bmp(0, 0, pic256.bmp); load_8bit_bmp(200, 200, hello.bmp); getchar(); closegraph(); 程序8bitbmp.c4.2 显示24bit bmp图片例12: 程序24bitbmp.c先定义了一个用户自定义函数load_24bit_bmp(), 再在函数main()中调用此自定义函数于
16、坐标(0,0)处显示一张24bit bmp图片pic.bmp。程序24bitbmp.c及配套图片文件打包下载链接:#include #include #include int load_24bit_bmp(int x, int y, char *filename) FILE *fp = NULL; byte *p = NULL; /* pointer to a line of bmp data */ byte *vp = _vp + (y*_width + x) * (_color_bits/8); dword width, height, bmp_data_offset, bytes_per
17、_line, offset; int i; p = malloc(1024L * 3); /* memory for holding a line of bmp data */ if(p = NULL) /* cannot allocate enough memory for drawing 1 line */ goto display_bmp_error; fp = fopen(filename, rb); if(fp = NULL) /* cannot open bmp file */ goto display_bmp_error; fread(p, 1, 0x36, fp); /* re
18、ad BMP head */ if(*(word *)p != 0x4D42) /* check BMP signature */ goto display_bmp_error; /* not a BMP file */ if(*(word *)(p+0x1C) != 24) goto display_bmp_error; /* not a 24-bit-color BMP file */ width = *(dword *)(p+0x12); height = *(dword *)(p+0x16); bmp_data_offset = *(dword *)(p+0x0A); fseek(fp
19、, bmp_data_offset, SEEK_SET); /* skip BMP head */ bytes_per_line = (width * 3 + 3) / 4 * 4; /* must be multiple of 4 */ for(i=height-1; i=0; i-) /* draw from bottom to top */ fread(p, 1, bytes_per_line, fp); /* read a line of bmp data */ offset = i * 1024 * 3; memcpy(vp+offset, p, width*3); free(p);
20、 fclose(fp); return 1;display_bmp_error: if(p != NULL) free(p); if(fp != NULL) fclose(fp); return 0;main() int driver=0, mode=VESA_1024x768x24bit; initgraph(&driver, &mode, ); load_24bit_bmp(0, 0, pic.bmp); getchar(); closegraph(); 程序24bitbmp.c五、文字输出5.1 文本模式下的字符输出文本模式下只能输出英文,不能输出中文。如果不考虑输出的坐标位置,则可以调
21、用printf()、puts()输出字符串;如果要在指定坐标位置输出字符串,则可以先调用函数gotoxy()把光标定位到指定位置,再调用函数puts()输出字符串。例13: 程序text1.c调用gotoxy()控制输出坐标,先在坐标(1,1)处输出字符串Hello,Tom!,再在坐标(2,2)处输出字符串Hello,Jerry。#include #include main() clrscr(); / 清屏 gotoxy(1,1); puts(Hello,Tom!); gotoxy(2,2); puts(Hello,Jerry!); getchar(); 程序text1.c请注意gotoxy(
22、)函数中, 横坐标及纵坐标都是以1为基的,即(1,1)相当于实际坐标(0,0)。在文本模式下,除了调用gotoxy(),还可以使用视频指针_vp来控制输出的坐标及内容。例14: 程序text2.c使用指针vp控制输出坐标及颜色和内容,先在坐标(0,0)处输出黑色背景白色前景的字符串Hello,Tom!,再在坐标(1,1)处输出蓝色背景红色前景的字符串Hello,Jerry。#include #include void putsxy(int x, int y, char *s, char color) char *vp = _vp + (y*_width+x)*2; int i = 0; whi
23、le(si != 0) *vp = si; *(vp+1) = color; vp += 2; i+; main() clrscr(); putsxy(0, 0, Hello,Tom!, BLACK4 | WHITE); putsxy(1, 1, Hello,Jerry!, BLUE4 | RED); getchar(); 程序text2.c5.2 图形模式下的字符输出5.2.1 图形模式下的英文输出图形模式下可调用outtextxy()在指定坐标位置输出一个英文字符串。例15: 程序outtext.c在坐标(100,100)处输出白色字符串Hello,Tom!,再在坐标(200,200)处输
24、出红色字符串Hello,Jerry!。#include #include main() int driver=0, mode=VESA_1024x768x24bit; initgraph(&driver, &mode, ); / 默认颜色为白色outtextxy(100,100, Hello,Tom!); setcolor(0xFF0000); / 设置颜色为红色 / 其中red=0xFF, green=0x00, blue=0x00/ 注意图形模式下的颜色不能使用RED、GREEN、BLUE / 等常数, 而应该用RGB成份进行定义 outtextxy(200,200, Hello,Jerr
25、y!); getchar(); closegraph(); 程序outtext.c请注意,outtextxy()输出字符串的颜色是指前景色,该颜色由setcolor()函数指定。outtextxy()并不描绘字符串的背景, 也就是说setbkcolor()函数指定的背景色对outtextxy()无任何影响。另外,outtextxy()是按8*16点阵输出字符,即字体大小是固定的。5.2.2 图形模式下的中文输出图形模式下可以自己编程读取汉字的点阵字库描出16*16个点。例16: 程序hz.c读取点阵字库hzk中我字的16*16点阵共32字节信息并在屏幕中间位置画出该字。程序hz.c及相关的字库
26、文件hzk打包下载链接: 程序hz.c通过画一个4*4的方块来描绘一个点,因此实际上把汉字放大了4倍。但是,放大以后的汉字呈明显的锯齿形。为了克服点阵汉字不能放大的缺陷,我们可以使用TTF曲线字库来输出汉字。其中快速输出可以通过调用函数get_ttf_text_pic()及draw_picture()实现,慢速输出可以通过调用函数out_ttf_text_xy()实现。例17: 程序ttftest.c演示了TTF字体的快速输出及慢速输出两种方式。程序ttftest.c及配套字库打包下载链接:六、声音输出6.1 扬声器输出例18: 程序music.c演示了如何控制杨声器发声,演奏一首歌。程序mu
27、sic.c下载链接:6.2 声卡输出例19: 程序sound.c演示了如何调用函数play_wave()及play_midi()输出wav波形文件及midi音乐文件。程序sound.c及配套声音文件打包下载链接:七、输入7.1 键盘输入char x;scanf(%c, &x);x = getchar();上述两个函数在输入一个字符时需要敲回车表示输入的结束;输入的符号会显示在屏幕上;一些特殊的键无法输入如上下左右方向键。函数bioskey()可以代替上述函数,并且克服以上3个不足之处。int key;key = bioskey(0); 其中key是一个16位整数。若当前键盘缓冲区是空的,则执行
28、bioskey(0)会等待用户敲键;若当前键盘缓冲区非空,则执行bioskey(0)会把键盘缓冲区中的键读走,不会等待用户输入。bioskey(1)用来检测键盘缓冲区是否为空,若缓冲区为空,则bioskey(1)返回0,否则返回非零。什么是键盘缓冲区? CPU能在运行程序时处理外部中断(interrupt)。当用户按下某个键时,键盘会向CPU发出一个中断请求,此时CPU会暂停正在运行的程序而转去处理键盘中断,处理的结果是把当前按住的键读走并存放到键盘缓冲区中。键盘缓冲区是一个队列(queue),相当于一个数组。例20: 程序blkctrl1.c演示了如何用bioskey(0)控制键移动屏幕上的一个方块。程序blkctrl1.c下载链接:例21: 程序blkctr12.c演示了如何用bioskey(1)检测键盘缓冲区从而控制方块做随机运动。程序blkctrl2.c下载链接: 除了使用bioskey()控制键盘外,还可以用键盘中断来控制键盘。使用键盘中断不仅可以读取bioskey()无法读取的键如Ctrl、Shift、Alt、CapsLock等,而且可以在用户按下某个键的瞬间作出实时响应。例22: 程序blkctr13.c演示了如何用键盘中断控制方块的移动。程序blkctrl3.c下载链接:7.2 鼠标输入鼠标要用到int 33h中断
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1