/* * 很久没在TC下写过程序了,本以为一个下拉菜单不出三小时就可以OK谁知道从昨天上午 * 开始到今天上午才完成。当然这里学到了些东西,以前没用过函数指针,现在这个下拉 * 菜单的菜单处理函数都用到了函数指针,调用时是直接通过函数指针,这简化了程序的 * 编写但实际上是不能那样的不同的菜单项应该有不同的处理函数,不过作为学习还是可 * 以的;以前没搞过远堆的内存,这次本来想用远堆来保存屏幕状态,但老是出错,最后 * 还是搞了个全局变量。 * 程序从 main()开始首先初始化界面,然后由用户选择菜单以调用不同的函数,最后通 * 过 ESC 键或者选择 EXIT 菜单退出。整个操作只有 ESC,回车键 和 方向键 有效。本来 * 还想设置菜单的快捷键,以及设计一些 3D 效果,考虑到初学者的接收能力和程序的复杂 * 度,最后还是从简了。 * 记得开始学 C 的时候自己就很想编个下拉菜单,那时候无从下手,对下拉菜单感到很神秘 * 嘿嘿,其实没什么,就是下面这样的。写了详细的注释供初学者参考,学了差不多两年了 * 还是改不掉写代码的坏习惯,变量名没有见名知义,神秘数字从天而降 …… * 不知道大家是怎么写代码的,我一写就停不下来,一搞就是好几个小时,肚子饿得咕 * 咕叫,下楼都没劲,整个人就像散了架。埃,难怪说程序员做不了几年,希望自己不在那样 * 希望天下程序员身体健康 . * ----- 江南孤峰 ------ * 2007 -- 3 -- 22 */ /*** *** 下拉式菜单程序, 编译环境 TC 点击下载源码 *** 转载请注明出处:http://lingdlz.programfan.com ***/#include <stdio.h>#include <conio.h> /* 键盘键值 */#define ESC 0x011b#define DOWN 0x5000#define LEFT 0x4b00#define RIGHT 0x4d00#define UP 0x4800#define ENTER 0x1c0d /* 一般常量宏 */#define SHOW_HIGH BLACK /* 高亮显示子菜单 */#define SHOW_NORMOL WHITE /* 正常显示子菜单 */#define MAIN_MENU_C CYAN /* 当前菜单显示背景色 */#define MENU_LENGTH 20 /* 子菜单名的字符长度 */#define MAIN_MENU_LENGTH 10 /* 主菜单名的长度限制 */ /* 菜单以及子菜单结构 */typedef struct menuItem{ /* 子菜单结构 */ char name[MENU_LENGTH]; /* 菜单选项 */ void (*pFun)(char *name); /* 函数指针 */}TypeMenuItem; typedef struct menu{ /* 菜单结构 */ int count; /* 子菜单数目 */ char name[MENU_LENGTH]; /* 菜单名 */ TypeMenuItem *pItem; /* 指向子菜单 */}TypeMenu; char video[2048]; /* 用来保存屏幕 */ /* 初始化屏幕界面 */void InitFace(void){ textbackground(SHOW_HIGH); textcolor(SHOW_NORMOL); clrscr(); gotoxy(24,3); printf("POPUP MENU (c)2007 -- 2088 BY DENG"); window(10,4,70,21); textbackground(RED); clrscr(); window(12,5,68,20); textbackground(SHOW_HIGH); clrscr(); window(12,5,68,7); textbackground(BLUE); clrscr();}/* 以 show[高亮或者正常]方式在屏幕输出字符串 txt */void WriteText(int x,int y,int xx,int yy,char *txt,int show){ window(x,y,xx,yy); textbackground(show); textcolor((show == SHOW_HIGH ? SHOW_NORMOL : SHOW_HIGH)); clrscr(); gotoxy(2,1); cprintf("%s",txt);}/* 退出程序 */void MyExit(void){ gotoxy(1,2); printf("press any key to exit ..."); getch(); exit(0);}/* 菜单处理函数,实际应用应该根据不同需要设置这些函数 */void menu1_fun1(char* txt){ cprintf("I get:[ %s ]",txt);}void menu1_fun2(char* txt){ cprintf("I get:[ %s ]",txt);}void menu1_fun3(char* txt){ cprintf("I get:[ %s ]",txt);}void menu1_fun4(char* txt){ cprintf("I get:[ %s ]",txt); MyExit();}void menu2_fun1(char* txt){ cprintf("I get:[ %s ]",txt);}void menu2_fun2(char* txt){ cprintf("I get:[ %s ]",txt);}void menu2_fun3(char* txt){ cprintf("I get:[ %s ]",txt);}void ShowHelp(char* txt){ cprintf("I get:[ %s ]",txt); gotoxy(1,2); cprintf("Use Destination key to move"); gotoxy(1,3); cprintf("Use Enter key to select "); gotoxy(1,4); cprintf("Use ESC Key to Exit");}void ShowAbout(char* txt){ cprintf("I get:[ %s ]",txt); gotoxy(1,2); cprintf("The program is write by JiangNanGuFeng"); gotoxy(1,3); cprintf("Only for study,you can update and send"); gotoxy(1,4); cprintf("But you can't delete the followed info"); gotoxy(1,5); cprintf("MY QQ: 403324669\nEmail: lingdlz@163.com"); gotoxy(1,6); cprintf("MY Email: lingdlz@163.com"); gotoxy(1,7); cprintf("MY Blog:http://lingdlz.programfan.com"); gotoxy(1,8); cprintf("Welcome to join QQ group : 28011342"); gotoxy(16,9); cprintf("-- 2007 - 3 - 22 --");}/* 绘制菜单条 */void DrawMenu(TypeMenu pMenu[],int count){ int i,xleft = 13,xright = xleft+MAIN_MENU_LENGTH; WriteText(xleft,6,xright,6,pMenu[0].name,MAIN_MENU_C); for(i = 1; i < count; i ++){ xleft = xright + 2; /* 2 是菜单之间的分隔长度 */ xright = xright + MAIN_MENU_LENGTH + 2; WriteText(xleft,6,xright,6,pMenu[i].name,SHOW_NORMOL); }}/* 设置相应坐标 flag 为 0 取主菜单坐标,否则取下拉菜单的坐标 */void SetCoordinate(int *x,int *y,int *xx,int *yy,int cMenu,int cItem){ int xleft = 13,xright = xleft + MAIN_MENU_LENGTH; *x = xleft + cMenu * (MAIN_MENU_LENGTH + 2); if(cItem){ *y = *yy = 6 + cItem; /* 2 是菜单之间的分隔长度 */ *xx = xright + cMenu * (MAIN_MENU_LENGTH + 2) + MENU_LENGTH - MAIN_MENU_LENGTH; } else{ *xx = xright + cMenu * (MAIN_MENU_LENGTH + 2); *y = *yy = 6; }}/* 显示子菜单 */void SpreadMenu(TypeMenu pMenu[],int cMenu){ int i,x,y,xx,yy; SetCoordinate(&x,&y,&xx,&yy,cMenu,1); WriteText(x,y,xx,y,pMenu[cMenu].pItem[0].name,SHOW_HIGH); for(i = 1,y ++; i < pMenu[cMenu].count; y ++,i ++) WriteText(x,y,xx,y,pMenu[cMenu].pItem[i].name,SHOW_NORMOL);}/* 程序运行的主要函数 */void RunProgram(TypeMenu pMenu[],int count){ int MenuSpread,temp; /* 菜单是否下拉 */ int cMenu,cItem; /* cMenu 当前菜单 cItem 当前子菜单 */ int x,xx,y,yy,uKey; /* uKey 接收用户输入 */ MenuSpread = cMenu = cItem = 0; while(1){ while(!kbhit()) ; /* 等待按键 */ uKey = bioskey(0); switch(uKey){ case ENTER: if(MenuSpread && cItem){ puttext(12,7,68,21,video); window(14,8,66,19); /* 信息输出区 */ textcolor(WHITE); textbackground(BLACK); clrscr(); /* 下面调用处理函数 */ pMenu[cMenu].pItem[cItem-1].pFun( pMenu[cMenu].pItem[cItem-1].name ); MenuSpread = cItem = 0; } else{ /* 菜单下拉 */ gettext(12,7,68,21,video); SpreadMenu(pMenu,cMenu); MenuSpread = 1; /* 标记菜单已经下拉 */ cItem = 1; /* 第一个子菜单高亮 */ } break; case LEFT: case RIGHT: SetCoordinate(&x,&y,&xx,&yy,cMenu,0); WriteText(x,y,xx,yy,pMenu[cMenu].name,SHOW_NORMOL); if(MenuSpread){ if(uKey == LEFT) cMenu = (cMenu == 0 ? count-1 : cMenu-1); else cMenu = (cMenu == count-1 ? 0 : cMenu+1); puttext(12,7,68,21,video); SpreadMenu(pMenu,cMenu); cItem = 1; } else{ if(uKey == LEFT) cMenu = (cMenu == 0 ? count-1 : cMenu-1); else cMenu = (cMenu == count-1 ? 0 : cMenu+1); } SetCoordinate(&x,&y,&xx,&yy,cMenu,0); WriteText(x,y,xx,yy,pMenu[cMenu].name,MAIN_MENU_C); break; case UP: case DOWN: if(MenuSpread){ SetCoordinate(&x,&y,&xx,&yy,cMenu,cItem); WriteText(x,y,xx,yy,pMenu[cMenu].pItem[cItem-1].name,SHOW_NORMOL); temp = cItem; if(uKey == DOWN) cItem = (pMenu[cMenu].count == cItem ? 1 : cItem+1); else cItem = (cItem == 1 ? pMenu[cMenu].count : cItem-1); if(temp > cItem) y = yy = y - temp + cItem; else y = yy = y + cItem - temp; WriteText(x,y,xx,yy,pMenu[cMenu].pItem[cItem-1].name,SHOW_HIGH); } else if(uKey == DOWN){ /* 菜单下拉 */ gettext(12,7,68,21,video); SpreadMenu(pMenu,cMenu); MenuSpread = 1; /* 标记菜单已经下拉 */ cItem = 1; /* 第一个子菜单高亮 */ } break; case ESC: window(14,8,66,19); clrscr(); MyExit(); default: break; } }} void main(void){ TypeMenu pMenu[3] = { 4,"FILE",NULL, 3,"EDIT",NULL, 2,"HELP",NULL }; TypeMenuItem menu1[] = { "MENU1_FILE_OPEN",menu1_fun1, "MENU1_FILE_SAVE",menu1_fun2, "MENU1_FILE_NEW",menu1_fun3, "EXIT",menu1_fun4 }; TypeMenuItem menu2[] = { "MENU2_EDIT_CUT",menu2_fun1, "MENU2_EDIT_COPY",menu2_fun2, "MENU2_EDIT_FIND",menu2_fun3 }; TypeMenuItem menu3[] = { "HELP_ITEM",ShowHelp, "HELP_ABOUT",ShowAbout }; pMenu[0].pItem = menu1; pMenu[1].pItem = menu2; pMenu[2].pItem = menu3; InitFace(); DrawMenu(pMenu,3); RunProgram(pMenu,3);}

评论