已阅读5页,还剩8页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
操作系统实验报告界面设计l 菜单菜单包括菜单栏,菜单,菜单项,一个菜单栏可以包括n个菜单,一个菜单可以包括菜单项。c语言设计菜单的思想是用双向链表,先保存绘图区的内容,再在上面画菜单。l 菜单结构图菜单栏菜单1菜单2菜单n.尾指针头指针当前指向菜单菜单项1菜单项2。菜单项n头指针其他菜单项结构类似结尾指针l 数据结构1. 菜单栏:typedef struct menubar_sint number,x,y,barheight,baritemwidth;/*number用来记录菜单项的数目,x,y用来记录菜单栏在屏幕上的位置,barheight用来控制菜单栏的高度,baritemwidth用来控制每项菜单的宽度*/struct menu_s *mhead; /*指向第一个菜单*/struct menu_s *mtail; /*指向最后一个菜单*/struct menu_s *mpoint; /*当用户按下左右箭头时用来记录指向那个菜单,初始指向mhead*/void (* docommand)(); /*菜单时间的处理函数*/menubar;2. 菜单:typedef struct menu_sint number; /*菜单是菜单栏中的第几项*/int subwidth; /*菜单项的宽度*/int subcount; /*菜单项的数目*/char *content; /*菜单显示的字符串/struct menu_s *next; /*指向下一个菜单,如果是结尾菜单,则为null*/struct menu_s *before; /*指向前一个菜单,如果是头菜单,则为null*/struct submenu_s *sub; /*指向当前激活的菜单项*/struct submenu_s *head; /*指向第一个菜单项*/struct submenu_s *tail; /*指向最后一个菜单项*/menu;3. 菜单项:typedef struct submenu_sint number; /*菜单项是菜单中的第几项*/int isactive; /*是否激活*/char *content; /*显示的字符串*/struct submenu_s *next; /*指向下一个菜单项*/struct submenu_s *before; /*指向前一个菜单项*/submenu;l 函数实现1. 菜单构造函数/*该函数的功能主要是根据指定的menutitle字符串,往菜单栏中添加一项菜单*/void addmenu(char *menutitle)if(mb=null)/*如果mb(全局menubar类型的变量)为null,说明没有初始化菜单栏,要初始化*/if(mb=(menubar *)malloc(sizeof(menubar)=null)doerror(system error);mb-number=0; /*菜单栏中菜单数目为0*/mb-mpoint=mb-mhead=mb-mtail=null;mb-x=0;mb-y=0; /*位置于屏幕上(0,0)*/mb-barheight=18; /*菜单栏高度为18*/mb-baritemwidth=100; /*每项菜单的宽度为100*/mb-docommand=docommand; /*设置事件处理函数为docommand()*/if(mb-mtail=null) /*如果mb-mtail为null,说明要先构造mb-mhead*/if(mb-mhead=(menu *)malloc(sizeof(menu)=null)doerror(system error);mb-mhead-before=null;mb-mtail=mb-mhead;else if(mb-mtail-next=(menu *)malloc(sizeof(menu)=null)doerror(system error);mb-mtail-next-before=mb-mtail;mb-mtail=mb-mtail-next;mb-mtail-number=mb-number; /*当前添加进去的菜单位置,下面有mb-number的自加*/mb-mtail-subwidth=0; /*菜单项的宽度为0*/mb-mtail-subcount=0; /*菜单项数目为0/mb-mtail-content=menutitle; /*把菜单的字符串指针指向menutitle*/mb-mtail-next=null;mb-mtail-sub=mb-mtail-head=mb-mtail-tail=null; /*把菜单项全部置null*/mb-number+;/*菜单栏中number加1,表示加进去了一个菜单*/ 2. 菜单项构造函数/*该函数的功能是根据menu指定的字符串,往该菜单中添加以itemtitle为字符串的菜单项比如additem(“file”,”open”)则执行向file菜单中添加一项itemtitle菜单项*/void additem(char *menu,char *itemtitle) mb-mpoint=mb-mhead; /*先把指针指向菜单头,这里借用mb中的mpoint为了不用额外的变量*/ while(mb-mpoint!=null) if(stricmp(mb-mpoint-content,menu)=0) /*遍历menu链表,如果找到一项和menu指定字符串相等的,则记录下来,跳出,*/ break; mb-mpoint=mb-mpoint-next; if(mb-mpoint-tail=null) /*如果tail为空,则说明没有构造头节点head*/ if(mb-mpoint-head=(submenu *)malloc(sizeof(submenu)=null) doerror(system error); mb-mpoint-head-before=null; mb-mpoint-sub=mb-mpoint-tail=mb-mpoint-head; else if(mb-mpoint-tail-next=(submenu *)malloc(sizeof(submenu)=null) doerror(system error); mb-mpoint-tail-next-before=mb-mpoint-tail; mb-mpoint-tail=mb-mpoint-tail-next; if(strlen(itemtitle)mb-mpoint-subwidth) mb-mpoint-subwidth=strlen(itemtitle); /*该语句主要计算一下刚加进来的菜单项的字符数,如果比菜单的宽度还要大,则把该宽度赋值给subwidth,主要是为了画菜单是宽度足够*/ mb-mpoint-subcount+;/*菜单项数目加一*/ mb-mpoint-tail-number=mb-mpoint-subcount; mb-mpoint-tail-isactive=0; mb-mpoint-tail-content=itemtitle; mb-mpoint-tail-next=null; 3. 绘画菜单栏void drawmenu() mb-mpoint=mb-mhead; rectangle(0,0,getmaxx()-1,mb-y+mb-barheight);/*画一个方框*/ while(mb-mpoint!=null)outtextxy(mb-mpoint-number*mb-baritemwidth+mb-x+5,mb-y+6,mb-mpoint-content); /*在菜单栏中逐项画出菜单的内容*/mb-mpoint=mb-mpoint-next;4. 绘画当前激活的菜单void drawsubmenu()submenu *temp;int x; /*x记录当前画菜单的x位置*/x=mb-mpoint-number*mb-baritemwidth+mb-x;temp=mb-mpoint-head;copyimage(x,mb-barheight+2,x+mb-mpoint-subwidth*8+5,(mb-mpoint-subcount+1)*mb-barheight+3); /*保存绘画区的内容,copyimage为自写的函数*/setfillstyle(1,getbkcolor();bar(x,mb-barheight+2,x+mb-mpoint-subwidth*8+5,(mb-mpoint-subcount+1)*mb-barheight+3); /*用背景色把绘画区覆盖一下*/rectangle(x,mb-barheight+2,x+mb-mpoint-subwidth*8+5,(mb-mpoint-subcount+1)*mb-barheight+3); /*画一个方框*/while(temp!=null)if(temp-isactive) /*如果是当前激活的菜单,则画一个红色方框背景*/setfillstyle(1,red);bar(x+2,temp-number*mb-barheight+4,x+mb-mpoint-subwidth*8+3,(temp-number+1)*mb-barheight-1);outtextxy(x+5,temp-number*mb-barheight+5,temp-content);temp=temp-next;4. 进入菜单/*根据menu指定的字符串,说明用户从哪项菜单进入菜单,如gotomenucur(”file”)说明用户激活了“file”菜单*/void gotomenucur(char *menu)mb-mpoint=mb-mhead;while(mb-mpoint-next!=null)if(stricmp(mb-mpoint-content,menu)=0)break;mb-mpoint=mb-mpoint-next;mb-mpoint-sub=mb-mpoint-head;mb-mpoint-sub-isactive=1;drawsubmenu();5. 菜单按键处理void menukey()int key;while(1)key=get_key();switch(key)case key_left: /*说明用户按下了向左按键,mb-mpoint应该向前移一项*/mb-mpoint-sub-isactive=0;backimage(mb-mpoint-number*mb-baritemwidth+mb-x,mb-barheight+2);if(mb-mpoint-before!=null) /*如果当前已经是mhead了,应该指向mtail*/mb-mpoint=mb-mpoint-before;elsemb-mpoint=mb-mtail;mb-mpoint-sub=mb-mpoint-head;mb-mpoint-sub-isactive=1;drawsubmenu();/*重画菜单,跳出*/break;case key_right: /*说明用户按下了向右键,解释同key_left*/mb-mpoint-sub-isactive=0;backimage(mb-mpoint-number*mb-baritemwidth+mb-x,mb-barheight+2);if(mb-mpoint-next!=null)mb-mpoint=mb-mpoint-next;elsemb-mpoint=mb-mhead;mb-mpoint-sub=mb-mpoint-head;mb-mpoint-sub-isactive=1;drawsubmenu();break;case key_up: /*说明用户按下了向上键,应把当前激活的菜单项向上移一项*/mb-mpoint-sub-isactive=0;backimage(mb-mpoint-number*mb-baritemwidth+mb-x,mb-barheight+2);if(mb-mpoint-sub-before!=null)mb-mpoint-sub=mb-mpoint-sub-before;elsemb-mpoint-sub=mb-mpoint-tail;mb-mpoint-sub-isactive=1;drawsubmenu();break;case key_down: /*说明用户按下了向下键,当前菜单项应向下移一项*/mb-mpoint-sub-isactive=0;backimage(mb-mpoint-number*mb-baritemwidth+mb-x,mb-barheight+2);if(mb-mpoint-sub-next!=null)mb-mpoint-sub=mb-mpoint-sub-next;elsemb-mpoint-sub=mb-mpoint-head;mb-mpoint-sub-isactive=1;drawsubmenu();break;case enter: /*说明用户按下了回车键,调用mb-docommand()*/mb-mpoint-sub-isactive=0;backimage(mb-mpoint-number*mb-baritemwidth+mb-x,mb-barheight+2);mb-docommand();return;case esc: /*说明用户按下了退出键,把拷贝的屏幕区域放回,不作任何处理*/mb-mpoint-sub-isactive=0;backimage(mb-mpoint-number*mb-baritemwidth+mb-x,mb-barheight+2);return;游标与滚屏l 思想在屏幕上显示的是两个队列,一个是等待队列,一个是就绪队列。设置了一个游标,可以用上下键移动指向每个进程,然后对指向进程进行各种操作,包括挂起,解挂,删除。我设置的屏幕上最多只能显示12个进程,就绪最多6个,等待最多6个,那么当进程多于此数时,在用户按上下键时,应该有滚屏功能。滚屏的思想如下:假设有就绪队列里有n1个进程,每个进程编号1,2,3.n1-1,n1。等待队列中有n2个进程,每个进程编号1,2,3n2-1,n2。假设当前游标指向的进程编号小于6,则绘画1到6个进程(如果进程数小于6则画出所有进程),如果当前游标指向的进程编号为n(n6),则绘画n6到n个,这样就实现了滚屏。当当前游标位置位于就绪队列结尾,则当用户按下向下按键时,应该将游标移动到等待队列的第一个;当当前游标位置位于就绪队列第一个,则当用户按下向上按键时,应该移动到等待队列最后一个;同理,当当前游标位于等待队列队尾对首时,应移动就绪队列队首队尾。l 函数实现因为我把等待队列和就绪队列放在同一个链表里,所以要实现上面的功能可能有点problem,但多用几个函数就能实现。1. /*这个函数用来给每个进程编号*/void updateprocess()int i=1,j=1;process *temp;temp=phead;while(temp)if(temp-isrun) /*给就绪队列中的进程编号*/temp-pos=i+;else /*给等待队列中的进程编号*/temp-pos=j+;temp=temp-next;2. /*这个函数用来得到列表中就绪队列中的第一个*/process *getfirstrun() process *temp; if(!phead) return null; temp=phead; while(temp!=null) if(temp-isrun) /*找到第一个,就跳出循环*/ break; temp=temp-next; return temp-isrun?temp:null; /*如果找到就返回,否则就返回null,因为可能存在唯一一个等待队列中的*/ 3. /*该函数用来获取列表中就绪队列中的最后一个*/ process *gettailrun() process *temp; if(!ptail) /*如果列表为空,则返回null*/ return null; temp=ptail; /*从列表尾部开始找*/ while(temp!=null) if(temp-isrun) /*如果找到,就跳出循环*/ break; temp=temp-before; return temp-isrun?temp:null; /*判断找到的是不是就绪队列中的如果不是就返回null,因为可能存在只有一个等待队列中的*/ 4. /*这个函数用来找相对于p的下一个就绪队列中的进程*/ process *getnextrun(process *p) process *temp; if(!p) return null; temp=p-next; while(temp!=null) if(temp-isrun) /*如果找到,就跳出循环*/ break; temp=temp-next; return temp; 5. /*这个函数用来找相对于p的前一个就绪队列中的进程*/ process *getbeforerun(process *p) process *temp; if(!p) return null; temp=p-before; while(temp!=null) if(temp-isrun) break; temp=temp-before; return temp; 6. /*这个函数用来找等待队列中的第一个,一下三个函数原理跟就绪队列中的操作函数一样,只是把查找的条件改成!temp-isrun*/ process *getfirstready() process *temp; if(!phead) return null; temp=phead; while(temp!=null) if(!temp-isrun) break; temp=temp-next; return temp-isrun?null:temp; 7. process *gettailready() process *temp; if(!ptail) return null; temp=ptail; while(temp!=null) if(!temp-isrun) break; temp=temp-before; return temp-isrun?null:temp; 8. process *getnextready(process *p) process *temp; if(!p) return null; temp=p-next; while(temp!=null) if(!temp-isrun) break; temp=temp-next; return temp; 9. process *getbeforeready(process *p) process *temp; if(!p) return null; temp=p-before; while(temp!=null) if(!temp-isrun) break; temp=temp-before; return temp; 10. /*这个函数用来得到下一个游标的位置*/void getnext() process *temp; if(phead=ptail)/*如果链表中只有一个进程,则什么也不处理,返回*/ ppoint=phead; return; if(ppoint=gettailrun()/*如果当前游标位置是就绪队列中的最后一个*/ temp=getfirstready();/*则指向第一个等待队列*/ ppoint=temp?temp:getfirstrun(); else if(ppoint=gettailready()/*如果当前游标位置是等待队列中的最后一个*/ temp=getfirstrun();/*则指向就绪队列中的第一个*/ ppoint=temp?temp:getfirstready(); else if(ppoint-isrun) /*如果当前队列在就绪队列中移动*/ ppoint=getnextrun(ppoint); /*移向就绪队列中的下一个*/ else ppoint=getnextready(ppoint); /*移向等待队列中的下一个*/ 11. /*这个函数用来得到上一个游标的位置,基本的解释同getnext()差不多*/ void getbefore() process *temp;if(phead=ptail) ppoint=phead;return; if(ppoint=getfirstrun() temp=gettailready(); ppoint=temp?temp:gettailrun(); else if(ppoint=getfirstready() temp=gettailrun(); ppoint=temp?temp:gettailready(); else if(ppoint-isrun) ppoint=getbeforerun(ppoint); else ppoint=getbeforeready(ppoint); 12. /*按键处理函数*/void key_u_d(int key)switch(key)case key_down:if(!phead) ppoint=null;else getnext();break;/*如果按下的是向下键*/case key_up:if(!ptail) ppoint=null;else getbefore();break; /*如果按下的是向上键*/if(ppoint) /*drawl_r(int,int)这个函数根据传递进来的两个参数指明应该画的起始编号*/if(ppoint-pos6)if(ppoint-isrun)drawl_r(ppoint-pos-6,0);else drawl_r(0,ppoint-pos-6);else drawl_r(0,0);else drawl_r(0,0);获取用户按键c语言库函数提供的getch(),或bioskey()在处理字符和菜单输入时有点麻烦,改写了一个函数int get_key() union regs rg; rg.h.ah=0; int86(0x16,&rg,&rg); if(rg.h.al=0)/*说明按下了修饰键,把这个值左移8位*/return rg.h.ah=48&key=57|key=8) /*如果按下的是数字键或者是退格键*/if(key=8) /*如果是退格键,就用背景色把原来的字符画一遍,相当于覆盖,然后去掉结尾一个,用前景色画字符,就相当于删掉一个字符(实际上也删掉了)*/color=getcolor();setcolor(getbkcolor();outtextxy(x+10,y+20,strcat(desc,number);setcolor(color);number-i=0; /*这句相当于删掉一个字符*/else if(ipos6) /*因为每个队列最多只能显示6个队列,所以当当前光标指向的进程的pos6时,pos一定是底部pos=6;else pos=ppoint-pos;bar(1-ppoint-isrun)*450,(pos-1)*50+80,(1-ppoint-isrun)*450+15,(pos-1)*50+85);/*画一个游标if(stop) /*stop是全局变量(为这是一个模拟程序,所以当用户想暂停或者什么的,可以暂停)果stop是true,则什么事都不做return;i=getnum(1); /*获取就绪队列中的进程总数*/j=getnum(0); /*获取等待队列中的进程总数*/if(i+j)=0) /*如果两个队列为空*/stop=1;fresh();/*刷新一下屏幕*/return;if(i0&canrun) /*如果就绪队列中的进程数小于maxrun(maxrun为就绪队列中的最大数目)且等待队列不为空,且有足够的内存(maxrun为true时表示有足够内存)*/getfromeready();/*从等待队列中选取一个优先级最高,时间最少的*/coverfront();/*把游标重画一遍(这里放这个函数好像有点多余)*/gettime(&t2);time=(t2.ti_hour-t1.ti_hour)*60*60*100+(t2.ti_min-t1.ti_min)*60*100+(t2.ti_sec-t1.ti_sec)*100+t2.ti_hund-t1.ti_hund; /*计算两次执行handle的时间差,其实可以用gettime()这个库函数,但当时没发现。*/runtime-=time; /*runtime是时间片大小,是个全局变量*/drawsector();/*画屏幕中间的时间片转盘*/if(runtimeisrun)*screenweidth,这样,如果它是就绪队列中的(它的isrun是1),它就在屏幕的左边,如果它是等待队列中的(它的isrun是0),它就在屏幕的右边。关于集成图形驱动做成exe文件在tc里头,生成的exe文件如果是文本模式的,则可以运行,而如果是图形模式的,生成的exe老是提示你没有初始化图形驱动,可以把图形驱动集成到graphic里头,方法如下:注册图形驱动:bgiobj egavga 回车得到egavga.objtlib libgraphics.lib+egavga.obj回车即可在程序中用registerbgidriver(egavga_driver);其它对应的如下cag.bgi cga_driverega.vga.bgi egavga_driverherc.bgiherc_driveratt.bgiatt_driverpc3270.bgipc3270_driveribm8514.bgiibm8514_driver注册字体:bgiobj trip|litt|sans|goth分别对应字体trip.chr|litt.chr|sans.chr|goth.chrtlib libgraphics.lib+litt.obj字型驱动registerbgifont()litt.chrtlib得到的字符名入samll_font源程序:#include #include #include #include #include #include #include /*包含一些必要的头文件*/#define intr 0x1c/*定义时钟中断号*/#define enter 13/*定义回车键*/#define key_up 18432/*定义向上键的整数值*/#define key_down 20480/*定义向下键的整数值*/#define key_left 19200/*定义向左键的整数值*/#define key_right 19712/*定义向右键的整数值*/#define alt_f 8448/*定义按下altf返回的整数值*/#define alt_s 7936/*定义按下alts返回的整数值*/#define alt_o 6144/*定义alto返回的整数值*/#define alt_h 8960/*定义alth返回的整数值*/#define esc 27/*定义esc返回的整数值,以上这些键值都是有get_key()函数获得*/typedef struct menubar_sint number,x,y,barheight,baritemwidth;struct menu_s *mhead;struct menu_s *mtail;struct menu_s *mpoint;void (* docommand)();menubar; /*定义一个菜单栏数据结构,在上面已经解释过*/typedef struct menu_sint number;int subwidth;int subcount;char *content;struct menu_s *next;struct menu_s *before;struct submenu_s *sub;struct submenu_s *head;struct submenu_s *tail;menu; /*定义一个菜单结构体,具体在上面已经解释过*/typedef struct submenu_sint number;int isactive;char *content;struct submenu_s *next;struct submenu_s *before;submenu; /*定义一个菜单项,具体已在上面解释过*/typedef struct process_tint pid;int isrun;int ishalt;int pos;int priority;int time_total;int time_left;long startaddr;long si
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 风景名胜区自行车租借协议
- 建筑安装工程承包合作协议
- 广告委托制作协议书
- 民间借款协议书的格式要求
- 私车出租给机构协议
- 2024年加盟经销合同范本
- 建筑工程劳务扩大分包合同完整2024年
- 2024正规版私人借款合同样本
- 吉林省农业产品订购协议
- 房产物业抵押借款协议
- 江苏省南京市鼓楼区2024-2025学年八年级上学期期中英语试卷(含答案解析)
- 四川公安基础知识模拟1
- 2024年中级司泵工职业鉴定考试题库(精练500题)
- 患者沟通技巧
- 18 牛和鹅 第一课时 课件
- 2024年宜宾人才限公司招聘高频难、易错点500题模拟试题附带答案详解
- DBT29-305-2024 天津市装配式建筑评价标准
- 冀教版七年级数学上册 2.6 角大小的比较(第二章 几何图形的初步认识 学习、上课课件)
- 创建“环保银行”(教学设计)-2024-2025学年四年级上册综合实践活动教科版
- 劳动教育学习通超星期末考试答案章节答案2024年
- 2024秋九年级英语上册 Module 3 Heroes Unit 3 Language in use教案(新版)外研版
评论
0/150
提交评论