C语言写的菜单"类"

来源:互联网 发布:淘宝开店做什么产品好 编辑:程序博客网 时间:2024/06/08 10:19

/************************************
名 称:菜单类 CMenu
作 者:freewind
版 本:v1.0
时 间:2006-08
Email:freewind22@163.com
*************************************/

#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <string.h>
#include <graphics.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#define HIDEMENU -1
#define MAXMENU 10
#define LINEHEI 16
enum ScreanMode{ TEXTMODE, IMAGEMODE };
struct MenuRetVal
{
 int MainMenu;
 int SubMenu;
};
struct Rectangle
{
 int Left;
 int Top;
 int Right;
 int Bottom;
};
struct Color
{
 int ForeColor;
 int BgColor;
 int FirstColor;
};
struct Menu
{
 int x;
 int y;
 int MainNum;
 int SubNum[MAXMENU];
 char MenuFirst[MAXMENU];
 int MainMenuPos[MAXMENU];
 char **MainMenu;
 char **SubMenu[MAXMENU];
 char ScanCode[30];
 void * TextBuf;
 struct MenuRetVal MenuValue;
 struct Rectangle MenuLoc;
 struct Color MenuColor;
 enum ScreanMode CurMode;
 struct MenuRetVal (* Show) (struct Menu *This, int isFocus );
 struct MenuRetVal (* ShowSubMenu)(struct Menu *, int, int );
 struct MenuRetVal (* PopMenu)(struct Menu *This, int isFocus );
 void (* SetXY) ( struct Menu *This, int x, int y );
 void (* SetColor)( struct Menu *This, struct Color);
 void (* AddMenu)( struct Menu *This, int, char * );
 void (* Close) ( struct Menu *This );
};
typedef enum ScreanMode SCREANMODE;
typedef struct Menu MENU;
typedef struct MenuRetVal MENURETVAL;
typedef struct Color COLOR;
char *gMenuMain[]={"File","Edit","Option","Help"};
char *gMenuFile[]={"New        Ctrl+N",
       "Open...    Ctrl+O",
       "Save...    Ctrl+S",
       "Save as...       ",
       "-",
       "Exit             "};
char *gMenuEdit[]={"Copy       Ctrl+C",
       "Cut        Ctrl+X",
       "Paste      Ctrl+V",
       "-",
       "Find...    Ctrl+F",
       "Replace... Ctrl+R",
       "-",
       "ShowTime   Ctrl+D"};
char *gMenuOption[]={"SetColor...      ",
      "SetFont...       ",
      "-",
      "Config...        "};
char *gMenuHelp[]  ={"Index          F1",
      "-",
      "About...         "};
char *gPopMenu[]={"menu_item_1",
      "menu_item_2",
      "menu_item_3",
      "-",
      "menu_item_4",
      "menu_item_5",
      "-",
      "menu_item_6",
      "menu_item_7"};
/******************************** GetKey ********************************/
void GetKey(int *ah,int *al)
{
 union REGS r;
 r.h.ah=0;
 int86(0x16,&r,&r);
 *ah=r.h.ah;
 *al=r.h.al;
}
/********************************** Init_Color ***************************/
void SetColor(MENU * This,COLOR curcolor)
{
 This->MenuColor=curcolor;
}
/********************************** Init_Data ****************************/
void SetXY(MENU * This,int x,int y)
{
 int i;
 This->x=x;
 This->y=y;
 /* SetMenuPos */
 for(i=0;i < This->MainNum;i++)
 {
  if (i==0)
   This->MainMenuPos[0]=x;
  else
   This->MainMenuPos[i]=This->MainMenuPos[i-1] + strlen( This->MainMenu[i-1] ) + 4;
 }
}
/*********************************** TEXT **********************************/
/***************************************************************************/
/******************************** TxtDrawBox *******************************/
void TxtDrawBox(int l,int t,int r,int b,int forecolor,int bgcolor)
{
 int i,j;
 textcolor(forecolor);
 textbackground(bgcolor);
 /* First Line */
 gotoxy(l,t);
 cprintf("%c",218);
 gotoxy(r,t);
 cprintf("%c",191);
 gotoxy(l+1,t);
 for(i=l+1;i<r;i++)
  cprintf("%c",196);
 /* Middle */
 for(i=t+1;i<b;i++)
 {
  gotoxy(l,i);
  for(j=l;j<=r;j++)
  {
   if(j==l || j==r) cprintf("%c",179);
   else cprintf(" ");
  }
 }
 /* Last Line */
 gotoxy(l,b);
 cprintf("%c",192);
 gotoxy(r,b);
 cprintf("%c",217);
 gotoxy(l+1,b);
 for(i=l+1;i<r;i++)
  cprintf("%c",196);
}
/******************************* ShowMenu *******************************/
void TxtShowMenu(MENU *This,int refresh)
{
 int i,j;
 int l,t,r,b,m,s;
 m=This->MenuValue.MainMenu;
 s=This->MenuValue.SubMenu;
 l=This->MainMenuPos[m] ,t=This->y+2;
 r=l+strlen(This->SubMenu[m][0])+1,b=t+This->SubNum[m];
 if (refresh && This->MenuLoc.Left > 0)
 {
  puttext(This->MenuLoc.Left,This->MenuLoc.Top,This->MenuLoc.Right,This->MenuLoc.Bottom,This->TextBuf);
 }
 if (refresh>0)
 {  
  gettext(l-1,t-1,r+1,b,This->TextBuf);
  This->MenuLoc.Left=l-1;
  This->MenuLoc.Top=t-1;
  This->MenuLoc.Right=r+1;
  This->MenuLoc.Bottom=b;
  TxtDrawBox(l-1,t-1,r+1,b,This->MenuColor.ForeColor,This->MenuColor.BgColor);
  textcolor(This->MenuColor.BgColor);
  textbackground(This->MenuColor.ForeColor);
  gotoxy(l-1,t-2);
  cprintf( " %s ",This->MainMenu[m] );
  textcolor(This->MenuColor.ForeColor);
  textbackground(This->MenuColor.BgColor);
  for (j=0;j < This->SubNum[m];j++)
  {
   if(!strcmp(This->SubMenu[m][j],"-"))
   {
    gotoxy(l-1,t+j);
    cprintf("%c",195);
    for(i=l;i<=r;i++)
     cprintf("%c",196);
    cprintf("%c",180);
   }
   else
   {
    gotoxy(l+1,t+j);
    cprintf( "%s",This->SubMenu[m][j] ); 
   }
  }/* end for */
 }/* end if */
 /* show curmenu */
 if(refresh>=0)
 {
  gotoxy(l,t+s);
  textcolor(This->MenuColor.BgColor);
  textbackground(This->MenuColor.ForeColor);
  for(i=l;i<=r;i++)
   cprintf("%c",' ');
  gotoxy(l+1,t+s);
  cprintf( "%s",This->SubMenu[m][s] );
 }
 gotoxy(1,This->MenuLoc.Top - 1);
 /*cprintf("%s","");*/
}
/******************************* SelectMenu ******************************/
void TxtSelectMenu(MENU *This,int isFocus)
{
 int ah,al;
 int i,j,l,t,r,n;
 TxtShowMenu(This,TRUE);
 while (isFocus){
  i=This->MenuValue.MainMenu;
  j=This->MenuValue.SubMenu;
  l=This->MainMenuPos[i] ,t=This->y+2;
  r=l+strlen( This->SubMenu[i][0] )+1;
  GetKey(&ah,&al);
  /* Hide MainMenu */
  if((ah==75 && al==0) || (ah==77 && al==0) || (ah==1 && al==27) || (ah==28 || al==13))
  {
   gotoxy(l-1,t-2);
   textbackground(This->MenuColor.BgColor);
   textcolor(This->MenuColor.FirstColor);
   cprintf(" %c",This->MainMenu[i][0]);
   textcolor(This->MenuColor.ForeColor);
   cprintf("%s  ", This->MainMenu[i] + 1 );
  }
  if (ah==1 && al==27){   /* ESC */
   This->MenuValue.MainMenu=-1;
   TxtShowMenu(This,HIDEMENU);
   isFocus=FALSE;
   continue;
  } 
  if (ah==75 && al==0){  /* <-  */  
   if (--This->MenuValue.MainMenu <0) This->MenuValue.MainMenu = This->MainNum-1;
   This->MenuValue.SubMenu=0;
   TxtShowMenu(This,TRUE);
   continue;
  }
  if (ah==77 && al==0){  /* -> */
   if (++This->MenuValue.MainMenu >This->MainNum-1 ) This->MenuValue.MainMenu=0;
   This->MenuValue.SubMenu=0;
   TxtShowMenu(This,TRUE);
   continue;
  }
  /* hide menu */
  if((ah==72 && al==0) || (ah==80 && al==0)){
   textcolor(This->MenuColor.ForeColor);
   textbackground(This->MenuColor.BgColor);
   gotoxy(l,t+j);
   for(n=l;n<=r;n++)
    cprintf("%c",' ');
   gotoxy(l+1,t+j);
   cprintf("%s",This->SubMenu[i][j]);
  }
  /*           */
  if (ah==72 && al==0){  /* Up  */
   j--;
   if (j<0) j=This->SubNum[i]-1;
   if (!strcmp( This->SubMenu[i][j] , "-")) j--;
   This->MenuValue.SubMenu=j;
   TxtShowMenu(This,FALSE);
  }
  if (ah==80 && al==0){  /* Down */
   j++;
   if (j > This->SubNum[i]-1) j=0;
   if (!strcmp(This->SubMenu[i][j],"-")) j++;
   This->MenuValue.SubMenu=j;
   TxtShowMenu(This,FALSE);
  }
  if (ah==28 && al==13){ /* Enter */
   isFocus=FALSE;
   TxtShowMenu(This,HIDEMENU); 
  } /* end if */
 }/* end while */
}
/*********************************** ShowSubMenu **************************/
MENURETVAL TxtShowSubMenu(MENU *This,int n,int isFocus)
{
 This->MenuValue.MainMenu=n;
 This->MenuValue.SubMenu=0;
 TxtSelectMenu(This,isFocus);
 return This->MenuValue;
}
/*********************************** Show *********************************/
MENURETVAL TxtShow(MENU * This,int isFocus)
{
 int i,j,ah,al;
 int ch;
 /* set color */
 textbackground(This->MenuColor.BgColor);
 /* Show MainMenu */
 gotoxy(1,This->y);
 clreol();
 for(i=0;i < This->MainNum;i++)
 {
  gotoxy(This->MainMenuPos[i],This->y);
  textcolor(This->MenuColor.FirstColor);
  cprintf("%c",This->MainMenu[i][0]);
  textcolor(This->MenuColor.ForeColor);
  cprintf("%s",This->MainMenu[i]+1);
 }
 /* SetFocus */
 while(isFocus)
 {
  GetKey(&ah,&al);
  if(ah==1 && al==27)   /* ESC */
  {
   This->MenuValue.MainMenu=-1;
   break;
  }
  if(al==0)  /* Alt + ? */
   for(i=0;i < This->MainNum;i++)
   {
    ch=This->MainMenu[i][0];
    if(ch >= 97) ch-=97; else ch-=65;
    if(ah==This->ScanCode[ch])
    {
     This->MenuValue.MainMenu=i;
     This->MenuValue.SubMenu=0;
     TxtSelectMenu(This,TRUE);
     isFocus=FALSE;
     break;
    }
   }
 }
 return This->MenuValue;
}

/********************************** PopMenu *******************************/
MENURETVAL TxtPopMenu(MENU *This,int isFocus)
{
 int i,n,ah,al,maxlen,len;
 int ch,l,t,r,b; 
 for(i=0,maxlen=0;i < This->MainNum;i++)
 {
  len=strlen(This->MainMenu[i]);
  if(len > maxlen) maxlen=len;
 }
 l=This->x-1,t=This->y-1;
 r=l+maxlen+3,b=t+This->MainNum+1;
 gettext(l,t,r,b,This->TextBuf);
 TxtDrawBox(l,t,r,b,This->MenuColor.ForeColor,This->MenuColor.BgColor);
 /* set color */
 textcolor(This->MenuColor.ForeColor);
 textbackground(This->MenuColor.BgColor);
 /* Show PopMenu */
 for(i=0;i < This->MainNum;i++)
 {
  if(!strcmp(This->MainMenu[i],"-"))
  {
   gotoxy(l,t+i+1);
   cprintf("%c",195);
   for(n=l+1;n<r;n++)
    cprintf("%c",196);
   cprintf("%c",180);
  }
  else
  {
   gotoxy(l+2,t+i+1);
   cprintf("%s",This->MainMenu[i] );
  }
 }
 /* SetFocus */
 This->MenuValue.MainMenu=-1;
 i=0;
 while(isFocus)
 {
  textcolor(This->MenuColor.BgColor);
  textbackground(This->MenuColor.ForeColor);
  gotoxy(l+1,t+i+1);
  for(n=l+1;n<r;n++)
   cprintf("%c",' ');
  gotoxy(l+2,t+i+1);
  cprintf("%s",This->MainMenu[i]);
  gotoxy(1,1);
  GetKey(&ah,&al);
  if(ah==1 && al==27)   /* ESC */
  {
   isFocus=FALSE;
   This->MenuValue.MainMenu=-1;
   puttext(l,t,r,b,This->TextBuf);
   continue;
  } 
  /* hide menu */
  if((ah==72 && al==0) || (ah==80 && al==0)){
   textcolor(This->MenuColor.ForeColor);
   textbackground(This->MenuColor.BgColor);
   gotoxy(l+1,t+i+1);
   for(n=l+1;n<r;n++)
    cprintf("%c",' ');
   gotoxy(l+2,t+i+1);
   cprintf("%s",This->MainMenu[i]);
  }
  /*           */
  if (ah==72 && al==0){  /* Up  */
   if (--i <0) i = This->MainNum-1;
   if(!strcmp(This->MainMenu[i],"-"))
    --i;
  }
  if (ah==80 && al==0){  /* Down */
   if (++i >This->MainNum-1 ) i=0;
   if(!strcmp(This->MainMenu[i],"-"))
    ++i;
  }
  if (ah==28 && al==13){ /* Enter */
   isFocus=FALSE;
   This->MenuValue.MainMenu=i;
   puttext(l,t,r,b,This->TextBuf);
  } /* end if */
 }
 return This->MenuValue;
}
/*********************************** IMAGE ********************************/
/**************************************************************************/
/******************************** GetL **********************************/
 int GetL(int icolor){
 return icolor<=7?icolor+8:15;
}
/******************************** ImgDrawBox ********************************/
void ImgDrawBox(int l,int t,int r,int b,int icolor){
 int lightcolor,darkcolor;

 lightcolor=GetL(icolor);
 setfillstyle(SOLID_FILL,icolor);
 setcolor(lightcolor);
 bar3d(l,t,r,b,0,0);

 /*darkcolor= (icolor==8?0:8);
 setcolor(darkcolor);
 line(r,t,r,b);
 line(l,b,r,b);*/
}

/********************************** PopMenu *******************************/
MENURETVAL ImgPopMenu(MENU *This,int isFocus)
{
 int i,n,ah,al,maxlen,len;
 int ch,l,t,r,b;
 for(i=0,maxlen=0;i < This->MainNum;i++)
 {
  len=strlen(This->MainMenu[i]);
  if(len > maxlen) maxlen=len;
 }
 l=This->x-1,t=This->y-1;
 r=l+(maxlen+2)*8,b=t+(This->MainNum)*LINEHEI+2;
 if( !This->TextBuf )
 {
  This->TextBuf = malloc( imagesize( l, t, r, b ) );
 }
 getimage(l,t,r,b,This->TextBuf);
 ImgDrawBox(l,t,r,b,This->MenuColor.BgColor);
 /* set color */
 setcolor(This->MenuColor.ForeColor);
 /* Show PopMenu */
 settextjustify(1,1);
 for(i=0;i < This->MainNum;i++)
 {
  if(!strcmp(This->MainMenu[i],"-"))
  {  
   setcolor( GetL(This->MenuColor.BgColor) );
   line(l+7,t+1+LINEHEI/2+i*LINEHEI,r-7,t+1+LINEHEI/2+i * LINEHEI);
  }
  else
  {
   setcolor( This->MenuColor.ForeColor );
   outtextxy(l+(r-l)/2,t+1+LINEHEI/2+i * LINEHEI,This->MainMenu[i]);
  }
 }
 /* SetFocus */
 This->MenuValue.MainMenu=-1;
 i=0;
 while(isFocus)
 {
  setfillstyle(SOLID_FILL,This->MenuColor.ForeColor);
  bar(l+2,t+2+i*LINEHEI,r-2,t+(i+1)*LINEHEI);
  setcolor(This->MenuColor.BgColor);
  outtextxy(l+(r-l)/2,t+1+LINEHEI/2+i * LINEHEI,This->MainMenu[i]);
  GetKey(&ah,&al);
  if(ah==1 && al==27)   /* ESC */
  {
   isFocus=FALSE;
   This->MenuValue.MainMenu=-1;
   putimage(l,t,This->TextBuf,COPY_PUT);
   continue;
  } 
  /* hide menu */
  if((ah==72 && al==0) || (ah==80 && al==0)){
   setfillstyle(SOLID_FILL,This->MenuColor.BgColor);
   bar(l+2,t+2+i*LINEHEI,r-2,t+(i+1)*LINEHEI);
   setcolor(This->MenuColor.ForeColor);
   outtextxy(l+(r-l)/2,t+1+LINEHEI/2+i * LINEHEI,This->MainMenu[i]);
  }
  /*           */
  if (ah==72 && al==0){  /* Up  */
   if (--i <0) i = This->MainNum-1;
   if(!strcmp(This->MainMenu[i],"-"))
    --i;
  }
  if (ah==80 && al==0){  /* Down */
   if (++i >This->MainNum-1 ) i=0;
   if(!strcmp(This->MainMenu[i],"-"))
    ++i;
  }
  if (ah==28 && al==13){ /* Enter */
   isFocus=FALSE;
   This->MenuValue.MainMenu=i;
   putimage(l,t,This->TextBuf,COPY_PUT);
  } /* end if */
 }
 return This->MenuValue;
}
/******************************* ShowMenu *******************************/
void ImgShowMenu(MENU *This,int refresh)
{
 int i,j;
 int l,t,r,b,m,s;
 m=This->MenuValue.MainMenu;
 s=This->MenuValue.SubMenu;
 l=This->x + (This->MainMenuPos[m]-This->x) * 8; t=This->y+17;
 r=l+(strlen(This->SubMenu[m][0])+2)*8,b=t+This->SubNum[m]*LINEHEI+2;

 if (refresh && This->MenuLoc.Left > 0)
 {
  putimage(This->MenuLoc.Left,This->MenuLoc.Top,This->TextBuf,COPY_PUT);
 }
 if (refresh>0)
 {  
  getimage(l,t,r,b,This->TextBuf);
  This->MenuLoc.Left=l;
  This->MenuLoc.Top=t;
  ImgDrawBox(l,t,r,b,This->MenuColor.BgColor);
  setcolor(This->MenuColor.BgColor);
  settextjustify(1,1);
  for (j=0;j < This->SubNum[m];j++)
  {
   if(!strcmp(This->SubMenu[m][j],"-"))
   {
    setcolor( GetL(This->MenuColor.BgColor) );
    line(l+7,t+1+LINEHEI/2+j*LINEHEI,r-7,t+1+LINEHEI/2+j * LINEHEI);
   }
   else
   {
    setcolor( This->MenuColor.ForeColor );
    outtextxy(l+(r-l)/2,t+1+LINEHEI/2+j * LINEHEI,This->SubMenu[m][j] );
   }
  }/* end for */
 }/* end if */
 /* show curmenu */
 if(refresh>=0)
 {
  setfillstyle(SOLID_FILL,This->MenuColor.ForeColor);
  bar(l+2,t+2+s*LINEHEI,r-2,t+(s+1)*LINEHEI);
  setcolor(This->MenuColor.BgColor);
  outtextxy(l+(r-l)/2,t+1+LINEHEI/2+s * LINEHEI,This->SubMenu[m][s]);
 }
}
/******************************* SelectMenu ******************************/
void ImgSelectMenu(MENU *This,int isFocus)
{
 int ah,al;
 int i,j,l,t,r,b,n;
 ImgShowMenu(This,TRUE);
 while (isFocus){
  i=This->MenuValue.MainMenu;
  j=This->MenuValue.SubMenu;
  l=This->x + (This->MainMenuPos[i]-This->x) * 8; t=This->y+17;
  r=l+(strlen(This->SubMenu[i][0])+2)*8,b=t+This->SubNum[i]*LINEHEI+2;
  GetKey(&ah,&al);
  /* Hide MainMenu
  if((ah==75 && al==0) || (ah==77 && al==0) || (ah==1 && al==27) || (ah==28 || al==13))
  {
   gotoxy(l-1,t-2);
   textbackground(This->MenuColor.BgColor);
   textcolor(This->MenuColor.FirstColor);
   cprintf(" %c",This->MainMenu[i][0]);
   textcolor(This->MenuColor.ForeColor);
   cprintf("%s  ", This->MainMenu[i] + 1 );
  }*/
  if (ah==1 && al==27){   /* ESC */
   This->MenuValue.MainMenu=-1;
   ImgShowMenu(This,HIDEMENU);
   isFocus=FALSE;
   continue;
  } 
  if (ah==75 && al==0){  /* <-  */  
   if (--This->MenuValue.MainMenu <0) This->MenuValue.MainMenu = This->MainNum-1;
   This->MenuValue.SubMenu=0;
   ImgShowMenu(This,TRUE);
   continue;
  }
  if (ah==77 && al==0){  /* -> */
   if (++This->MenuValue.MainMenu >This->MainNum-1 ) This->MenuValue.MainMenu=0;
   This->MenuValue.SubMenu=0;
   ImgShowMenu(This,TRUE);
   continue;
  }
  /* hide menu */
  if((ah==72 && al==0) || (ah==80 && al==0)){
   setfillstyle(SOLID_FILL,This->MenuColor.BgColor);
   bar(l+2,t+2+j*LINEHEI,r-2,t+(j+1)*LINEHEI);
   setcolor(This->MenuColor.ForeColor);
   outtextxy(l+(r-l)/2,t+1+LINEHEI/2+j * LINEHEI,This->SubMenu[i][j]);
  }
  /*           */
  if (ah==72 && al==0){  /* Up  */
   j--;
   if (j<0) j=This->SubNum[i]-1;
   if (!strcmp( This->SubMenu[i][j] , "-")) j--;
   This->MenuValue.SubMenu=j;
   ImgShowMenu(This,FALSE);
  }
  if (ah==80 && al==0){  /* Down */
   j++;
   if (j > This->SubNum[i]-1) j=0;
   if (!strcmp(This->SubMenu[i][j],"-")) j++;
   This->MenuValue.SubMenu=j;
   ImgShowMenu(This,FALSE);
  }
  if (ah==28 && al==13){ /* Enter */
   isFocus=FALSE;
   ImgShowMenu(This,HIDEMENU); 
  } /* end if */
 }/* end while */
}

/*********************************** ShowSubMenu **************************/
MENURETVAL ImgShowSubMenu(MENU *This,int n,int isFocus)
{
 This->MenuValue.MainMenu=n;
 This->MenuValue.SubMenu=0;
 ImgSelectMenu(This,isFocus);
 return This->MenuValue;
}
/*********************************** Show *********************************/
MENURETVAL ImgShow(MENU * This,int isFocus)
{
 int i,j,ah,al;
 int l,t,r,b;
 int ch;
 unsigned int maxsize=0,size;
 /* set color */
 cleardevice();
 /* Show MainMenu */
 setfillstyle(SOLID_FILL,This->MenuColor.BgColor);
 setcolor(This->MenuColor.ForeColor);
 settextjustify(0,0);
 l=This->x; t=This->y; b=t+16;
 for(i=0;i < This->MainNum;i++)
 {
  r=l+( strlen(This->MainMenu[i]) + 4 )*8;
  bar(l,t,r,b);
  outtextxy(l+5,t+13,This->MainMenu[i]);
  line(l+5,t+14,l+11,t+14);
  l=r;
 }
 /* SetFocus */
 while(isFocus)
 {
  GetKey(&ah,&al);
  if(ah==1 && al==27)   /* ESC */
  {
   This->MenuValue.MainMenu=-1;
   break;
  }
  if(al==0)  /* Alt + ? */
   for(i=0;i < This->MainNum;i++)
   {
    ch=This->MainMenu[i][0];
    if(ch >= 97) ch-=97; else ch-=65;
    if(ah==This->ScanCode[ch])
    {
     This->MenuValue.MainMenu=i;
     This->MenuValue.SubMenu=0;
     if( !This->TextBuf )
     {
      for( i=0; i < This->MainNum; i++)
      {
       size=imagesize(0,0,(strlen( This->SubMenu[i][0] )+2 )*8,This->SubNum[i]*LINEHEI+2 );
       if(size>maxsize) maxsize=size;
      }
      This->TextBuf = malloc(maxsize);
     }
     ImgSelectMenu(This,TRUE);
     isFocus=FALSE;
     break;
    }
   }
 }
 return This->MenuValue;
}
/*********************************** PUBLIC *******************************/
/**************************************************************************/

/*********************************** AddMenu ******************************/
void AddMenu(MENU *This,int n,char *submenu)
{
 int i;
 for(i=0;This->SubMenu[i] && i<MAXMENU ;i++)
  ;
 if(i==MAXMENU) return;
 This->SubMenu[i]=submenu;
 This->SubNum[i]=n;
 if(i<MAXMENU-1) This->SubMenu[i+1]=0;
}
/************************************ Close ************************************/
void Close( MENU *This )
{
 free(This->TextBuf);
 switch( This->CurMode )
 {
 case IMAGEMODE:
  closegraph();
 }
}
/********************************** Init_Mode *****************************/
void Init_Graph(MENU *This)
{
 int gdriver=DETECT,gmode,errorcode;
 switch(This->CurMode)
 {
 case IMAGEMODE:
  gmode=getgraphmode();
  if( gmode < 0 ){
   initgraph(&gdriver, &gmode, "G://turboc2//");
   errorcode = graphresult();
   if (errorcode != grOk) /* an error occurred */
   {
    printf("Graphics error: %s/n", grapherrormsg(errorcode));
    printf("Press any key to halt:");
    getch();
    exit(1); /*terminate with an error code */
   }
  }
  /* set member function */
  This->Show=ImgShow;
  This->PopMenu=ImgPopMenu;
  This->ShowSubMenu=ImgShowSubMenu;
  break;
 case TEXTMODE:
  textmode(BW80);
  /* set member function*/
  This->Show=TxtShow;
  This->PopMenu=TxtPopMenu; 
  This->ShowSubMenu=TxtShowSubMenu;
  This->TextBuf=malloc(1024);
  break; 
 }
 This->SetXY=SetXY;
 This->SetColor=SetColor;
 This->AddMenu=AddMenu;
 This->Close=Close;
}
/*********************************** Init *****************************/
void Init(MENU * This,int n,char **mainmenu,SCREANMODE mode)
{
 COLOR c={9,7,13};

 This->MainMenu = mainmenu;
 This->MainNum=n;
 This->CurMode=mode;
 This->SubNum[0]=0;
 This->SubMenu[0]=0;
 This->MenuValue.MainMenu=-1;
 This->MenuLoc.Left=0;
 This->TextBuf=0;
 /* SetScanCode            A   BCD   EF GH   IJKLMN   O   P   Q   R   S   T   UV   WX   YZ*/
 strcpy(This->ScanCode,"/x1e/x30. /x12!/"#/x17$%&21/x18/x19/x10/x13/x1f/x14/x16//x11-/x15,");

 Init_Graph(This);
 SetXY(This,3,1);
 SetColor(This,c);
}
/************************************ main *************************************/
void main()
{
 int ah,al;
 MENU Mnu1;
 MENU PopMenu1;
 MENU PopMenu2;
 MENURETVAL RetVal;
 COLOR c1={ 10, 3, 14 };
 COLOR c2={ 1, 10, 13 };

 Init( &Mnu1, 4, gMenuMain, TEXTMODE );
 AddMenu( &Mnu1, 6, gMenuFile );
 AddMenu( &Mnu1, 8, gMenuEdit );
 AddMenu( &Mnu1, 4, gMenuOption );
 AddMenu( &Mnu1, 3, gMenuHelp );

 Mnu1.SetColor( &Mnu1, c2);
 RetVal=Mnu1.Show( &Mnu1,TRUE );
 Mnu1.Close( &Mnu1 );

 Init( &PopMenu2, 9, gPopMenu, IMAGEMODE );
 PopMenu2.SetXY( &PopMenu2, 50, 50 );
 PopMenu2.SetColor( &PopMenu2, c1 );
 RetVal=PopMenu2.PopMenu( &PopMenu2, TRUE);

 PopMenu2.Close( &PopMenu2 );
}