第13章图形和用户界面技术_第1页
第13章图形和用户界面技术_第2页
第13章图形和用户界面技术_第3页
第13章图形和用户界面技术_第4页
第13章图形和用户界面技术_第5页
已阅读5页,还剩44页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

.,第13章图形和用户界面技术,本章导读界面是程序的一个窗口,是用户与程序之间的桥梁。友善的用户界面,不仅可以使用户感觉赏心悦目、使用方便、自然有趣,更能提高程序的使用效率。因此,用户界面是应用程序不可缺少的组成部分,而用户界面分为文本形和图两种。本章将学习图形显示技术和菜单设计,并为编辑器添加菜单,完善用户界面。本章的教学目标:掌握图形显示技术;了解汉字显示方法;掌握文本方式和方式下的菜单设计;为编辑器添加菜单,完善用户界面,完成编辑器的最终设计目标。,.,第13章图形和用户界面技术,13.1文本窗口的程序设计13.2文本下拉式菜单设计13.3图形显示技术13.4汉字显示技术13.5图形方式下的菜单设计13.6菜单的综合应用,.,13.1文本窗口的程序设计,13.1.1窗口定义TurboC使用函数window()定义屏幕窗口,函数原型为:voidwindow(intx1,inty1,intx2,inty2);参数x1,y1是窗口左上角的坐标,x2,y2是右下角的坐标。并规定整个屏幕左上角的坐标为(1,1),右下角的坐标为(80,25)。例如,定义一个窗口,它的左上角在屏幕的第5列第10行处,宽为30列,高15行,可调用函数:window(5,10,35,25);,.,13.1.2窗口操作函数,.,窗口设计举例,【例13.1】创建一个宽64列,高17行的窗口。窗口左上角坐标是(7,7),背景颜色为白色,字符为蓝色。然后在窗口正中间显示若干字符,如图13-1所示,图13-1创建窗口,.,#includeconio.hmain()charname80;textbackground(WHITE);/*设置白色背景颜色*/clrscr();/*清屏,使设置的背景颜色生效*/window(7,7,71,24);textbackground(5);/*设置5号背景颜色*/textcolor(BLUE);/*设置蓝色文本颜色*/clrscr();/*清屏,使设置的颜色生效*/gotoxy(16,8);cprintf(Onewindowiscreated!);getch();window(1,1,80,25);/*恢复全屏幕窗口*/textbackground(BLACK);/*恢复0号背景颜色*/textcolor(7);/*恢复7号前景颜色*/clrscr();/*清屏,使设置的颜色生效*/,.,13.2文本下拉式菜单设计,13.2.1设计目标主菜单分为:File、Edit、Search和Option四项。其中:File项包含5个子菜单:New,Open,Save,SaveAs,Exit;Edit项包含6个子菜单:Cut,Copy,Paste,Del,SelectedAll,Edit;Search项包含2个子菜单:Find,Replace;Option项包含4个子菜单:Undo,Redo,Config,Help;(1)启动menu,进入程序主菜单,利用左、右(、)键,可操作主菜单间左右移动;(2)利用上、下(、)键,可控制子菜单间上下移动;(3)回车确认光带所选菜单项;(4)选择菜单File/Exit,退出系统。,.,13.2.2菜单设计方法,编写下拉式菜单的一般步骤:保存屏幕弹出前的矩形区域;显示菜单正文;产生光条;读取按键信息;根据菜单项的选择,处理相应的事务;恢复屏幕弹出前的原始状态;连编成一个完整的程序。,.,1保存和恢复屏幕区域,保存屏幕可用gettext()函数,其函数原型为:intgettext(intx1,inty1,intx2,inty2,void*buffer);将屏幕上以(x1,y1)为左上角、(x2,y2)右下角的矩形区域的文本内容存入buffer指针指向的内存空间。内存所用字节数为:(y2-y1+1)X(x2-x1+1);恢复保存的屏幕内容可调用函数puttext()完成,其函数原型为:intputtext(intx1,inty1,intx2,inty2,void*buffer);将gettext()函数存入内存buffer中的文字内容拷贝到屏幕指定位置,.,2.显示菜单正文,利用光标定位函数gotoxy()和字符串显示函数cputs()就可完成。voiddisp_menu_item(intx,inty,intfcolor,intbcolorchar*string)textbackground(bcolor);textcolor(fcolor);gotoxy(x,y)cputs(string);函数的功能是在屏幕(x,y)点,用背景颜色bcolor、字符颜色fcolor显示字符串指针string所指向的字符串。3产生光条最简单的方法是用不同的背景颜色和字符颜色重写光条的菜单项,调用函数disp_menu_item()完成。,.,4读取按键信息,菜单设计中最关键的一点是功能键的读取。而键盘上有两种键:ASCII码键和特殊功能键,为通用起见,我们编写了如下GetKey()函数,用来返回键值,当读取的键是普遍键时,返回其ASCII码值;如是特殊功能键时,返回大于256的整数。intGetKey(void)unionunsignedintx;unsignedchary2;key1;while(bioskey(1)=0);key1.x=bioskey(0);return(key1.y0=0?(key1.y1+256):key1.y0);,.,13.2.3程序框架及功能函数,1主程序框架voidmain(void)InitScreen();/*初始化屏幕*/WMainMenu();/*显示主菜单*/WSubMenu();/*显示子菜单*/SelectMenu();/*根据用户按键,处理相事务*/Quit();/*恢复屏幕*/,.,2菜单的框架函数(SelectMenu),约定:左、右移动键是主菜单间左右移动选择,由SlectMainMenu()函数实现;而上、下键是子菜单间上下移动选择,由SlectSubMenu()函数实现;回车键进入事务处理子函数SubFunGo(),由菜单项File/exit退出,其中:Mm是主菜单项变量,SmmMm是对应第Mm项菜单的子菜单项变量,LEFT、RIGHT、UPPER、DOWN是对应于左右、上下移动键的符号常量,注意与GetKey()函数返回值一致。voidSelectMenu(void)while(1)Key=GetKey();/*循环接受键盘输入*/if(Key=LEFT|Key=RIGHT)SlectMainMenu();/*主菜单左右选择*/if(Key=UPPER|Key=DOWN)SlectSubMenu();/*子菜单上下选择*/if(Key=ENTER)/*回车确认选项*/if(!SubFunGo()break;/*执行编辑命令操作*/,.,3.主菜单选择函数,voidSlectMainMenu(void)window(1,1,80,25);/*恢复主菜单光条*/disp_menu_item(SbXMm,1,14,3,MainMm);/*恢复屏幕*/puttext(SbXMm-2,2,SbXMm+SbWidMm+1,SbNumMm+4,buf);if(Key=LEFT)Mm=Mm=0?3:Mm-1;/*实现主菜单的循环*/if(Key=RIGHT)Mm=Mm=3?0:Mm+1;disp_menu_item(SbXMm,1,14,4,MainMm);/*设置光条*/WSubMenu();/*显示下拉式菜单*/,.,4.子菜单选择函数,voidSlectSubMenu(void)/*子菜单项的选择*/*光条恢复*/disp_menu_item(2,1+SmmMm,15,3,SubMmSmmMm);if(Key=UPPER)/*实现子菜单项的循环*/SmmMm=SmmMm=0?SbNumMm-1:SmmMm-1;if(Key=DOWN)SmmMm=SmmMm=SbNumMm-1?0:SmmMm+1;/*设置光条*/disp_menu_item(2,1+SmmMm,14,1,SubMmSmmMm);,.,13.3图形显示技术,13.3.1图形系统控制1图形系统的初始化用函数initgraph完成图形系统的初始化,函数原形为:voidfarinitgraph(intfar*gdriver,intfar*gmode,charfar*path)其中:gdriver为图形驱动程序,参见表13-2,在graphics.h中有相应的枚举常量,常用的有DETECT(自动检测)、EGA、VGA。gmode为图形适配器的工作模式,graphics.h中常用的枚举常量有EGAHI、VGAHI。path为查找图形驱动程序所用的路径名。2图形系统的关闭图形系统处理完毕后,需调用closegraph函数关闭图形系统,退出图形状态,函数原形为:voidfarclosegraph(void),.,13.3.2基本图形函数,TurboC提供了丰富的图形函数,一些基本的图形可经过直接调用图形函数而得到。对于一般的图形都可以由它们组合而成。基本的图形函数均包含在头文件graphics.h中,如下表13-3所示。,表13-3基本图形函数,.,13.3.3时钟程序,/*包含文件*/time_tltime;/*类型time_t即long*/structtm*pt;/*pt为指向时间结构tm的指针*/voidshowTime(void)/*以图形方式显示运转的时钟*/intRs=100;/*秒针长度*/intRc=130;/*时钟外圆圈半径*/doublealpha=2*PI/60.0;/*秒针1秒钟和分针1分钟所旋转的弧度数*/intx,y;/*时钟圆心坐标*/intxSecond,ySecond;/*秒针针尖位置坐标*/intdriver=DETECT,mode;initgraph(/*画时钟外圆圆圈*/,.,while(!kbhit()/*按下任一键则退出循环*/time(/*调用图形方式显示函数*/,.,13.4汉字显示技术,13.4.116点阵字模字库中的汉字按1616点阵模式存储,每个汉字由1616=256个点组成,占用162=32个字节单元。字节的每一位(bit)表示一个点的属性(1有亮点,0无亮点),连续的两个字节表示该汉字字模的一行,32个字节的排列序如图13-5所示。,.,13.4.2汉字的内码,在计算机内英文字符是用一个字节的ASCII代码表示,一般用七位表示128个字符,而最高位作为奇偶校验(或不用)。我国国标规定汉字用内码表示,内码为两个字节。为了与西文兼容,汉字系统的内码必须同时允许ASCII码和汉字内码的使用,两者之间不应冲突,所以规定每个字节只用7位(bit),若两个字节的最高位均为1,则该字符为汉字。,.,13.4.3字模的显示,汉字库分成若干区,每个区有94个汉字,每个汉字均有一个确定的区码和位码,知道了区位码也就相当于知道了汉字在字库中的位置,由于汉字的内码与区位码有一定的关系,所以只要通过汉字的内码就可以得到汉字的区位码,从而可以获得该汉字的字模,然后在图形方式下,读取字模的每一个字节的每一位即可按画点的方式在屏幕上显示出汉字。由于在中文DOS下,输入汉字时,其相应的内码已在程序中存在,即内码已在汉字的位置,如同在西文DOS下,输入英文字符时,其对应的ASCII码也在程序中存在一样,设某个汉字内码为十六进制数aaff,则区号qh和位号wh分别为:qh=aa0 xa0;wh=ff0 xa0;则该汉字在汉字库中的起始位置为(以字节为单位):offset=(94*(qh-1)+(wh-1)*32L;,.,连续读取32个字节就是该汉字的字模。对每个字节的每一位进行判断,如果是1就画点,否则就不画,这样就可以显示汉字来。因此,由汉字内码,从汉字库中读取字模的可用下函数实现:voidget_hzm(charincode,charbytes)unsignedcharqh,wh;unsignedlongoffset;qh=incode00 xa0;/*得到区号*/wh=incode10 xa0;/*得到位号*/offset=(94*(qh-1)+(wh-1)*32L;/*得到偏移位置*/fseek(fp,offset,SEEK_SET);/*定位字模首字节*/fread(bytes,1,32,fp);,.,voiddisp_hzm(intx,inty,intcolor,charbuf)/*显示字模的函数*/inti,j,k;for(i=0;i(7-k),.,【例13.4】在例13.3的三维直方图中添加汉字“三维直方图(中国深圳)”字样,如图13-6所示。分析:只要在例13.3的程序中添加get_hzm(),disp_hzm()和DisHz16X16()子函数,并在适当的位置插入打开汉字库、关闭文件程序段和调用函数DisHz16X16()的语句。程序清单如下(省略了未变动的语句和前面给出的函数):main()FILE*fp;./*初始化*/fp=fopen(“hzk16.dot”,”rb”);/*打开16点阵汉字库文件hzk16.dot*/.Bar3DDemo();DisHz16X16(100,10,4,12,”三维直方图(中国深圳)”);fclose(fp);getch();closegraph();,汉字显示的应用举例,.,1.对于24X24点阵的汉字库,如何修改显示程序DisHz16X16()?2.修改显示函数DisHz16X16(),将其放大两倍,课堂练习及思考,图13-6三维直方图,.,13.5.1屏幕的保存和恢复voidfargetimage(intx1,inty1,intx2,inty2,voidfar*mapbuf);voidfarputimage(intx1,inty1,voidfar*mapbuf,intop);unsignedfarimagesize(intx1,inty1,intx2,inty2);在利用getimage()函数保存屏幕时,必需用imagesize()计算被保存的左上角(x1,y1),右下角(x2,y2)的图形屏幕区域的全部内容所需要的字节数,然后再給mapbuf分配一个所求得的字节数的内存空间。调用putimage()函数,将保存在mapbuf指向的内存中的图象输出到左上角为(x1,y1)的位置上,其中,putimage()函数中的参数op规定如何把内存中的图象与对应屏幕运算方式,详见表13-4。,13.5图形方式下的菜单设计,.,【例13.6】利用getimage()和putimage()函数,显示一个沿sin()函数曲线运动的圆。voidmain(void)intgdrive=DETECT,gmode=VGAHI,i;void*buff=NULL;initgraph(/*清屏*/,屏幕的保存和恢复举例,.,dofor(i=0;i640;i+)delay(1000);/*延时*/*从内存复制图像显示到内存*/putimage(30+i,200+sin(i/60.0)*60.0,buff,COPY_PUT);while(!kbhit();/*反复显示运动过程直至按键*/if(buff!=NULL)free(buff);/*释放动态申请内存空间*/closegraph();/*退出图形系统*/,.,在图形方式下,显示菜单项的区域由左上角和右下角坐标确定,因此,我们必须将文本方式下的菜单项的显示函数:voiddisp_menu_item(intx,inty,intfcolor,intbcolorchar*string)textbackground(bcolor);textcolor(fcolor);gotoxy(x,y)cputs(string);修改为:voiddisp_menu_item(intx1,inty1,intx2,inty2,intfc,intbc,char*item)setfillstyle(1,bc);bar(x1,y1,x2,y2);DisHz16X16(x1+10,y1+4,bcolor,fc,item);,13.5.2菜单项的显示函数,.,凡是调用了disp_menu_item()、gettext()和puttext()的相关函数也必须作相应改动,诸如:WmainMenu()、WsubMenu()、SlectMainMenu(void)、SlectSubMenu(void)。修改后的代码请读者参考教材p292-293.,13.5.3其它相关函数的修改,.,13.5.4修改Wind()和InitScreen()函数,voidInitScreen()setfillstyle(1,1);bar3d(0,0,639,479,0,0);setfillstyle(1,3);bar3d(0,0,639,25,0,0);bar3d(0,430,639,450,0,0);setfillstyle(1,6);bar3d(0,450,639,479,0,0);setcolor(15);outtextxy(10,436,edithelp);outtextxy(10,460,mainhelp);,voidWind(intx1,inty1,intx2,inty2,intFrmTp,intBCl,intTCl)setfillstyle(1,BCl);bar(x1,y1,x2,y2);setcolor(TCl);if(FrmTp)rectangle(x1+2,y1+2,x2-2,y2-2);if(FrmTp=2)rectangle(x1+4,y1+4,x2-4,y2-4);,.,voidInitGr(void)/*添加图形初始化*/intGraphDrive=DETECT,GraphMode=VGAHI;detectgraph(,13.5.5添加InitGr()和Quit()函数,.,将原来以字符为单位定位变量的初始化语句:intSbWid4=10,10,10,10;intSbX4=5,15,23,32;改为以象素定位:intSbWid4=93,93,93,90;intSbX4=20,110,200,290;将西文菜单文本修改为中文:char*Main4=文件,编辑,查找,操作;char*Sub46=“新文件”,打开,保存,另存为,退出,裁剪,复制,粘贴,删除,”全选”,编辑,查找,替换,取消,恢复,设置,”帮助”;,13.5.6修改部分变量的初始化,.,为程序tedit6添加文本下拉菜单,实现第6章(图6-9)提出的设计目标。因此,下面将进一步优化tedit6,将13.2中编写的下拉式菜单程序框架emenu.c与程序tedit6.c整合,升级编辑器第七版tedit7。13.6.1编辑器第七版tedit7程序tedit7功能结构如图13-8所示。主菜单分为:File、Edit、Search和Option四项。,13.6菜单的综合应用,图13-8程序tedit7功能结构图,.,程序tedit7的开发,就是把程序tedit6.c与文本下拉式菜单程序框架emenu.c溶合在一起,在emenu.c的功能菜单中调用tedit6.c的功能函数。但不是简单的嵌套调用,因为它们的所有操作是在各自特定的窗口中进行的。所以,我们要设法在它们之间建立关联。分4步完成:(1)修改tedit6.c的屏幕最大显示字符行和列,使宽、高与emenu.c的可编辑文本窗口一致。以及程序中与之相关的语句,并取消功能操作提示help()函数。(2)改造部分功能函数,如字符串查找和替换函数(mysearch,myreplace),因为,在编辑状态下,需要提示信息和输入信息。将tedit6.c中的main函数改为edit编辑功能函数,注意提取初始化init函数、以及修改屏幕滚动函数。(3)以菜单程序框架为主函数,调用编辑器的功能函数。保留原操作方式,添加菜单选取方式。(4)按照多程序文件连编规则,重新整理、规范tedit6.c和emenu.c。把函数说明、全局变量加上static属性予以保护,以免同名造成混淆;而公用的变量或函数在其中之一程序文件中定义,在另一程序文件中说明是外部extern属性。,13.6.2程序tedit7的开发,.,1.修改屏幕最大显示行和列程序menu.c的窗口是设置在全屏幕(即25行,80列),除去主菜单、状态提示栏,可编辑窗口只是中间部分(20行,78列)。因此,该区域的大小应该为修改后tedit7的编辑屏幕区域大小。而程序tedit6.c是设置在全屏幕(即25行,80列),编辑文本窗口由宏定义MAX_LINES,LINE_LEN确定。你可以改变宏定义值,实现编辑文本窗口尺寸的变化。考虑到取消功能操作提示行和四周边框,因此,将tedit6.c中的宏定义:#defineLINE_LEN80#defineMAX_LENS24修改为:#defineLINE_LEN78#defineMAX_LENS20,13.6.3程序tedit6的改造,.,在字符串查找myserach()和替换myreplace()、文件存储save()和加载load()函数中,我们应将用户的输入在状态栏中进行,所以需要进行窗口的切换,为此,先定义两个窗口的切换函数:(1)从编辑窗口切换到状态栏voidgoto_propmt(void)window(1,25,80,25);/*切换到状态栏窗口*/clrline(1);gotoxy(20,1);textattr(0 x6e);(2)从状态栏恢复到编辑窗口voidgoto_edit(void)gotoxy(1,1);cputs(mainhelp);/*恢复提示*/window(2,3,79,22);/*恢复到编辑窗口*/textbackground(0);textcolor(7);,2.修改部分功能函数,.,在myserach()、myreplace()、save()和load()四个函数中,在提示用户输入时,将原来的光标定位一律用goto_prompt()替换;反之,完成输入后,返回到编辑状态之前,则用goto_edit()替换。例如,在myserach()中,粗斜体语句是替换或添加的,省去了未改变的部分。其它三个函数留给读者完成。,voidmysearch(void)charstr80,*p;intlen,i,k,j;goto_prompt();/*切换到状态栏窗口*/printf(inputsearchstring:);edit_gets(str);if(!str0)gotox_edit();/*恢复到编辑窗口*/gotoxy(point.scrnx,point.scrny);return;,.if(!*p)printf(notfind);gotox_edit();/*恢复到编辑窗口*/gotoxy(point.scrnx,point.scrny);return;.gotox_edit();/*恢复到编辑窗口*/gotoxy(point.scrnx,point.scrny);,.,(3)修改滚动函数因边框,需将上、下滚动函数scrollup()、scrolldn()中的语句r.h.ch=topy-1;r.h.cl=topx-1;r.h.dh=endy-1;r.h.dl=endx-1;替换为r.h.ch=topy-1+2;r.h.cl=topx-1+1;r.h.dh=endy-1+2;r.h.dl=endx-1+1;,.,(4)修改tedit6.c中的main函数为编辑功能子函数edit(),以被主程序调用。移出初始化函数init()。voidedit(void)unionunsignedinti;charch2;key;do/*循环接受用户输入*/while(bioskey(1)=0);/*检测键盘直到有击键才结跳出循环*/key.i=bioskey(0);/*读取键盘扫描码*/./*未改变*/while(key.ch0!=ESC);,.,(5)相关函数调用的修改把程序tedit6.c中初始化函数init()移到menu.c的主函数中。main()Screen();WMainMenu();init();WSubMenu();SelectMenu();Quit();return0;,.,1主程序框架voidmain(void)InitScreen();/*初始化;WMainMenu();/*显示主菜单*/init();WSubMenu();/*显示子菜单*/SelectMenu();/*菜单操作*/Quit();/*恢复文本模式;*/voidSelectMenu(void)while(1)Key=GetKey();/*循环接受键盘输入*/if(Key=LEFT|Key=RIGHT)SlectMainMenu();/*主菜单左右选择*/if(Key=UPPER|Key=DOWN)SlectSubMenu();/*子菜单上下选择*/if(Key=ENTER)/*回车确认选项*/SubFunGo();/*执行编辑命令操作*/,13.6.4程序框架及功能函数,.,(1)菜单程序与编辑器窗口的切换程序tedit6.c的窗口应定位于程序menu.c的可编辑文本窗口内。调用窗口创建函数window(2,3,79,22),就可把编辑器定位在menu.c的可编辑文本窗口内。修改函数Sele

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论