正文

下拉式菜单程序(C)2007-03-22 11:21:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/lingdlz/24184.html

分享到:

/*
 * 很久没在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);
}

阅读(6131) | 评论(8)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册