回 帖 发 新 帖 刷新版面

主题:[原创]菜单演示程序-《C高级实用程序设计》 王士元  p304 - p320

/*
    菜单演示程序

    《C高级实用程序设计》 王士元编著 清华大学出版社 p304 - p320
    
    TC3.0 下编译通过.对源代码略有修改。

    meteor135
    smith_135@163.com

    2005-5-21 1:11
*/
#include<graphics.h>
#include<alloc.h>
#include<process.h>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#include<dos.h>
#include<bios.h>
#include<conio.h>
#include<ctype.h>

#define INSERT  0x5200
#define ESC     0x001b
#define TAB     0x0f09
#define RETURN  0x000d
#define RIGHT   0x4d00
#define LEFT    0x4b00
#define UP      0x4800
#define DOWN    0x5000
#define BS      0x0e08
#define HOME    0x4700
#define END     0x4f00
#define PGUP    0x4900
#define PGDN    0x5100
#define DEL     0x5300
#define F1      0x3b00
#define F2      0x3c00
#define F3      0x3d00
#define F4      0x3e00
#define F5      0x3f00
#define F6      0x4000
#define F7      0x4100
#define F8      0x4200
#define F9      0x4300
#define F10     0x4400

#define MenuInGround        1
#define MenuActiveGround    2
#define MenuActiveItem      3
#define MenuInItem          4
#define MenuEdge            5
#define WindowEdge          6
#define WindowGround        7
#define PopWindow           8

#define WindowMinX 1
#define WindowMinY 25
#define WindowMaxX 638
#define WindowMaxY 478

void getitemcount(char **,int *,int *,int *);
void InitialGraphics(void);
void LoadMainMenu(void);
void LoadSubMenu(char **name,int ord);
int ManageSubMenu(void);
void ManageMainMenu(void);
void DisplayMainMenu(void);
int DisplaySubMenu(int ord);
void FuncProc(int ID);
void GoodBye(char *pcInf1,char *pcInf2);
void In_ActiveMainMenuItem(int select,char In_Active);
void In_ActiveSubMenuItem(int ord,int select,char In_Active);
int GetKey(void);
void MessageBox(char *Message);
void About(void);
void MoveText(void);
void Draw(void);
void GoodBye(char *pcInf1,char *pcInf2);
void ExitMenu(int ord);
int DisplaySubMenu(int ord);
void Help_page_show(void){return;};

unsigned char AllColors[20]={0,CYAN,LIGHTRED,YELLOW,BLACK,WHITE,LIGHTRED,BLUE,CYAN,9,10,11,12,13,14,15};

#define INUM    10  /* maximum 10 items in each MENU */
typedef struct _menu
{
    int coor[4];            /* The menu's area */
    int itemcoor[4*INUM];   /* max 10 item,each with x1,y1,x2,y2 */
    int itemdispxy[2*INUM]; /* Actually disp item name's X coor */
    char select;            /* selected item's ord */
    char itemnum;           /* The number of items in this menu */
    char **itemname;        /* item's name(point to static data) */
    int COMMAND_ID[INUM];   /* Key number */
}MENUTYPE;

MENUTYPE MainMenu,SubMenu[INUM];

static char *MainMenuItem[]={"File","Menu1","Menu2","Menu3","Menu4","Quit",0};

static char *SubMenuItem1[]=
{
    "Item11",
        "Item12",
        "Item13",
        "Item14",
        "Item15",
        "Item16",
        "Quit",
        0
};

static char *SubMenuItem2[]=
{
    "Item21",
        "Draw",
        "Item23",
        "Item24",
        "Item25",
        "Item26",
        "Item27",
        "Item28",
        0
};

static char *SubMenuItem3[]=
{
    "Item31...",
        "Item32...",
        "Item add......",
        "Item33",
        0
};

static char *SubMenuItem4[]=
{
    "Item41...",
        "Item42...",
        "Moving Text",
        "Item44",
        "Item45",
        "iteme**",
        0
};

static char *SubMenuItem5[]=
{
    "Item51...",
        "About...",
        "Item53",
        0
};

static char *SubMenuItem6[]=
{
    0
};

int maxx,texth,textw;
void * MenuImageBuf;

void main( )
{
    InitialGraphics();
    maxx=getmaxx();
    texth=textheight("text");
    textw=textwidth("t");

    LoadMainMenu();

    LoadSubMenu(SubMenuItem1,0);
    LoadSubMenu(SubMenuItem2,1);
    LoadSubMenu(SubMenuItem3,2);
    LoadSubMenu(SubMenuItem4,3);
    LoadSubMenu(SubMenuItem5,4);
    LoadSubMenu(SubMenuItem6,5);

    ManageMainMenu();
}

/*checked 2005年5月20日 23:58:03 */
void ManageMainMenu(void)
{
    unsigned key;
    int ID;

    DisplayMainMenu();

    for(key=0;;)
    {
        key=GetKey();
        switch(key)
        {
        case LEFT:
            In_ActiveMainMenuItem(MainMenu.select,0);
            if(MainMenu.select<1)   /*Already leftest item in mainmenu */
                MainMenu.select=MainMenu.itemnum-1;
            else
                MainMenu.select--;
            In_ActiveMainMenuItem(MainMenu.select,1);/* checked 2005年5月20日 23:58:03*/
            break;

        case RIGHT:
            In_ActiveMainMenuItem(MainMenu.select,0);
            if(MainMenu.select>MainMenu.itemnum-2)  /*already rightest */
                MainMenu.select=0;
            else
                MainMenu.select++;
            In_ActiveMainMenuItem(MainMenu.select,1);
            break;

        case DOWN:
        case RETURN:
            switch(MainMenu.COMMAND_ID[MainMenu.select])
            {
            case 5:     /* Exit to DOS */
                if(key==DOWN)
                    break;
                closegraph();
                GoodBye("Goodbye from","the MENU DEMO in graphics mode.");
                break;
            default:
                ID=ManageSubMenu();
                if(ID>=0)
                    FuncProc(ID);
                break;
            }
        }
    }
}


void FuncProc(int ID)
{
    switch(ID)
    {
    case 6:     /* 006 File|Quit */
        closegraph();
        GoodBye("GoodBye from","the MENU DEMO in graphics mode.");
        break;
    case 101:
        Draw();
        break;
    case 302:
        MoveText();
        break;
    case 401:
        About();
        break;
    default:
        /* Clear window */
        setfillstyle(SOLID_FILL,AllColors[WindowGround]);
        bar(WindowMinX,WindowMinY,WindowMaxX,WindowMaxY);

        /* dynamic show item text 2005年5月21日 1:07:50*/
        MessageBox(*(SubMenu[MainMenu.select].itemname + SubMenu[MainMenu.select].select));

        /*      MessageBox("This is an example!");*/

        break;
    }
}

回复列表 (共5个回复)

沙发

/* 2005年5月21日 0:26:12*/
/* ManageSubMenu() return an int value that is     */
/* ==-2:If there is a error                        */
/* ==-1:Return to main menu,nothing to do          */
/* ==0 or >0:the COMMAND_ID of a menu item         */
int ManageSubMenu(void)
{
    MENUTYPE * mn=&SubMenu[MainMenu.select];

    unsigned key;

    if(DisplaySubMenu(MainMenu.select))     /*Out of memery */
        return -2;

    for(key=0;;)
    {
        key=GetKey();

        switch(key)
        {
        case ESC:           /* return to MainMenu */
            ExitMenu(MainMenu.select);
            return -1;
        case UP:
            In_ActiveSubMenuItem(MainMenu.select,mn->select,0);
            if(mn->select>0)
                mn->select--;
            else
                mn->select=mn->itemnum-1;
            In_ActiveSubMenuItem(MainMenu.select,mn->select,1);
            break;
        case DOWN:
            In_ActiveSubMenuItem(MainMenu.select,mn->select,0);
            if(mn->select<mn->itemnum-1)
                mn->select++;
            else
                mn->select=0;
            In_ActiveSubMenuItem(MainMenu.select,mn->select,1);
            break;
        case LEFT:
            ExitMenu(MainMenu.select);
            In_ActiveMainMenuItem(MainMenu.select,0); /*2005年5月21日 0:25:04*/
            if(MainMenu.select<1)                        /*Already leftest item in mainmenu */
                MainMenu.select=(MainMenu.itemnum-1);
            else
                MainMenu.select--;
            In_ActiveMainMenuItem(MainMenu.select,1);   /*Light bar */
            if(DisplaySubMenu(MainMenu.select))         /*Out of memory */
                return -2;
            mn=&SubMenu[MainMenu.select];
            break;
        case RIGHT:
            ExitMenu(MainMenu.select);
            In_ActiveMainMenuItem(MainMenu.select,0);
            if(MainMenu.select>MainMenu.itemnum-2)      /*already rightest */
                MainMenu.select=0;
            else
                MainMenu.select++;
            In_ActiveMainMenuItem(MainMenu.select,1);
            if(DisplaySubMenu(MainMenu.select))         /* Out of memory */
                return -2;
            mn=&SubMenu[MainMenu.select];
            break;
        case RETURN:
            ExitMenu(MainMenu.select);
            return mn->COMMAND_ID[mn->select];
        }
    }
}


/* Checked 2005年5月20日 21:36:47 */
void LoadMainMenu()
{
    int count,totallen,maxlen,i,j=1;

    /*主菜单的两条对角线坐标*/
    MainMenu.coor[0]=0;
    MainMenu.coor[1]=0;
    MainMenu.coor[2]=maxx;
    MainMenu.coor[3]=3*texth;

    getitemcount(MainMenuItem,&count,&totallen,&maxlen);
    MainMenu.itemnum=count;

    maxlen=(maxx/textw-totallen)/count; /*length(char)between 2 items(horiz.)  */

    for(i=0,j=0;i<count;i++)
    {
        MainMenu.itemcoor[i*4]=j*textw;             /*  x1  */
        MainMenu.itemcoor[i*4+1]=MainMenu.coor[1];  /*  y1  */
        MainMenu.itemcoor[i*4+2]=textw*(j+maxlen+strlen(MainMenuItem[i]));
        /*  x2  */
        MainMenu.itemcoor[i*4+3]=MainMenu.coor[3];

        MainMenu.itemdispxy[i*2]=textw*(j+0.5*maxlen);  /* actuall disp X */
        MainMenu.itemdispxy[i*2+1]=texth;               /*  actuall disp Y */
        MainMenu.COMMAND_ID[i]=i;
        j+=maxlen+strlen(MainMenuItem[i]);
    }
    MainMenu.itemname=MainMenuItem;
}


void LoadSubMenu(char **name,int ord)
{
    int count,i,j,maxlen;

    getitemcount(name,&count,&i,&maxlen);
    SubMenu[ord].itemname=name;
    SubMenu[ord].itemnum=count;

    j=textw*(maxlen+2);
    if(j+MainMenu.itemcoor[4*ord]<maxx)     /*  left text justification is OK  */
    {
        SubMenu[ord].coor[0]=MainMenu.itemcoor[4*ord];    /* item's x1 */
        SubMenu[ord].coor[2]=SubMenu[ord].coor[0]+j;
    }
    else                                    /* Use right justification because of space */
    {
        SubMenu[ord].coor[2]=maxx;          /* left just use X2  */
        SubMenu[ord].coor[0]=SubMenu[ord].coor[2]-j;
    }
    SubMenu[ord].coor[1]=MainMenu.itemcoor[4*ord+3];    /* The item's y2 */
    SubMenu[ord].coor[3]=SubMenu[ord].coor[1]+count*(texth+6);

    /* 6-pixel between items of vert.menu */
    for(i=0;i<count;i++)
    {
        SubMenu[ord].itemcoor[i*4]=SubMenu[ord].coor[0];
        SubMenu[ord].itemcoor[i*4+1]=SubMenu[ord].coor[1]+i*(6+texth);
        SubMenu[ord].itemcoor[i*4+2]=SubMenu[ord].coor[2];
        SubMenu[ord].itemcoor[i*4+3]=SubMenu[ord].itemcoor[i*4+1]+texth+6;

        SubMenu[ord].itemdispxy[i*2]=SubMenu[ord].itemcoor[i*4]+textw;
        SubMenu[ord].itemdispxy[i*2+1]=SubMenu[ord].itemcoor[i*4+1]+3;
        SubMenu[ord].COMMAND_ID[i]=ord*100+i;
    }
}


/* checked in 2005年5月20日 23:39:02 */

void DisplayMainMenu(void)      /* Display main menu. */
{
    unsigned i;

    setcolor(AllColors[WindowEdge]);
    rectangle(0,0,getmaxx(),getmaxy());

    setcolor(AllColors[MenuEdge]);
    setfillstyle(SOLID_FILL,AllColors[MenuInGround]);
    bar3d(MainMenu.coor[0],MainMenu.coor[1],MainMenu.coor[2],MainMenu.coor[3],0,0);
    setcolor(AllColors[2]);

    MainMenu.select = 0 ;

    for(i=0;i<MainMenu.itemnum;i++)  /* */
    {
        if(MainMenu.select==i)
            In_ActiveMainMenuItem(i,1);
        else
            setcolor(AllColors[MenuInItem]);
        outtextxy((MainMenu.itemdispxy[i*2]),MainMenu.itemdispxy[i*2+1],MainMenu.itemname[i]);
    }
}

int DisplaySubMenu(int ord)     /* Display submenu */
{
    unsigned size,i;
    MENUTYPE *mn=&SubMenu[ord];

    size=imagesize(mn->coor[0],mn->coor[1],mn->coor[2],mn->coor[3]);

    /*
    Changed farmalloc to malloc and also changed farfree to free in function ExitMenu().
    Or else it will cause CPU error!
    2005年5月21日 0:30:48
    */
    if(NULL==(MenuImageBuf=(unsigned char *)malloc(size*2)))
    {
        clearviewport();
        outtextxy(100,100,"Out of memory!");
        outtextxy(100,110,"Press any key..");
        getch();
        return 1;
    }

    getimage(mn->coor[0],mn->coor[1],mn->coor[2],mn->coor[3],MenuImageBuf);

    setfillstyle(SOLID_FILL,AllColors[MenuInGround]);

    setcolor(AllColors[MenuEdge]);
    bar3d(mn->coor[0],mn->coor[1],mn->coor[2],mn->coor[3],0,0);

    for(i=0;i<mn->itemnum;i++)
    {
        if(i==mn->select)
            In_ActiveSubMenuItem(ord,i,1);
        else
        {
            setcolor(AllColors[MenuInItem]);
            outtextxy(mn->itemdispxy[i*2],mn->itemdispxy[i*2+1],mn->itemname[i]);
        }
    }

    return 0;
}

void ExitMenu(int ord)
{
    MENUTYPE *mn=&SubMenu[ord];
    if(MenuImageBuf)
    {
        putimage(mn->coor[0],mn->coor[1],MenuImageBuf,COPY_PUT);
        free(MenuImageBuf);
    }
}

void In_ActiveMainMenuItem(int select,char In_Active)
{
    MENUTYPE *tp=&MainMenu;
    int start,end,bot,top;

    start=tp->itemcoor[select*4]+8;
    top=tp->itemcoor[select*4+1]+2;
    end=tp->itemcoor[select*4+2]-8;
    bot=tp->itemcoor[select*4+3]-2;
    if(In_Active==0)        /* off */
    {
        setfillstyle(SOLID_FILL,AllColors[MenuInGround]);
        bar(start,top,end,bot);
        setcolor(AllColors[MenuInItem]);
        outtextxy(tp->itemdispxy[select*2],tp->itemdispxy[select*2+1],tp->itemname[select]);
    }
    else
    {
        setfillstyle(SOLID_FILL,AllColors[MenuActiveGround]);
        bar(start,top,end,bot);
        setcolor(AllColors[MenuActiveItem]);
        outtextxy(tp->itemdispxy[select*2],tp->itemdispxy[select*2+1],tp->itemname[select]);
    }
}


/* 2005年5月21日 0:21:25*/
void In_ActiveSubMenuItem(int ord,int select,char In_Active)
{
    MENUTYPE *tp=&SubMenu[ord];
    int start,end,bot,top;

    start=tp->itemcoor[select*4]+2;
    top=tp->itemcoor[select*4+1]+1;
    end=tp->itemcoor[select*4+2]-2;
    bot=tp->itemcoor[select*4+3]-1;
    if(In_Active==0)                /*  off */
    {
        setfillstyle(SOLID_FILL,AllColors[MenuInGround]);
        bar(start,top,end,bot);
        setcolor(AllColors[MenuInItem]);
        outtextxy(tp->itemdispxy[select*2],tp->itemdispxy[select*2+1],tp->itemname[select]);
    }
    else
    {
        setfillstyle(SOLID_FILL,AllColors[MenuActiveGround]);/*updated 2005年5月21日 0:20:56*/
        bar(start,top,end,bot);
        setcolor(AllColors[MenuActiveItem]);/*0:21:09*/
        outtextxy(tp->itemdispxy[select*2],tp->itemdispxy[select*2+1],tp->itemname[select]);        
    }
}

板凳

void InitialGraphics(void)
{
    int driver=DETECT,mode=0;
    int errorcode;

    initgraph(&driver,&mode,"C:\\TC\\BGI");
    /*  read result of initialization   */
    errorcode=graphresult();
    if(errorcode!=grOk)             /* an error occurred */
    {
        printf("Graphics error:%s\n",grapherrormsg(errorcode));
        printf("Press any key to halt:");
        getch();
        GoodBye("Graphics error.","Try again!");
    }
}

int GetKey(void)/*   */
{
    int key;

    key=bioskey(0);

    if(key==F1)
        Help_page_show();
    else if(key<<8)
    {
        key=key&0x00ff;         /* Get ASCII code  */
        if(isalpha(key))
            key=toupper(key);
    }
    return key;
}

static void getitemcount(char **s,int *count,int *len,int *maxlen)   /*   */
{
    int i,j;

    for((*maxlen)=0,(*len)=0,i=0;s[i]!=NULL;i++)
    {
        j=strlen(s[i]);
        (*len)+=j;
        if(j>(*maxlen))(*maxlen)=j;
    }
    (*count)=i;
}

void Draw(void)
{
    int x,x1,x2,y1,y2,ch;
    randomize();
    do
    {
        x1=random(WindowMaxX-WindowMinX)+WindowMinX;
        y1=random(WindowMaxY-WindowMinY)+WindowMinY;
        x2=random(WindowMaxX-WindowMinX)+WindowMinX;
        y2=random(WindowMaxY-WindowMinY)+WindowMinY;
        ch=random(16);
        setfillstyle(SOLID_FILL,ch);
        if(x1>x2)
        {
            x=x1;
            x1=x2;
            x2=x;
        }
        if(y1>y2)
        {
            x=y1;
            y1=y2;
            y2=x;
        }
        bar(x1,y1,x2,y2);
        delay(100);
    }while(!bioskey(1));
}

/* modified on 2005年5月21日 9:10:37*/
void About(void)
{
    int MidX,MidY,x1,y1,x2,y2,size;
    void *Buffer;

    MidX=(WindowMaxX-WindowMinX)/2;
    MidY=(WindowMaxY-WindowMinY)/2;

    x1=MidX-90;
    x2=MidX+90;
    y1=MidY-100;
    y2=MidY+100;
    size=imagesize(x1,y1,x2,y2);
    /*  Clear window  */
    
    setfillstyle(SOLID_FILL,AllColors[WindowGround]);
    bar(WindowMinX,WindowMinY,WindowMaxX-1,WindowMaxY-1);

    if((Buffer=malloc(size))==NULL)
    {
        outtextxy(100,100,"Out of memory!Press any key to continue.");
        getch();
    }
    else
    {
        getimage(x1,y1,x2,y2,Buffer);

        setfillstyle(SOLID_FILL,AllColors[PopWindow]);
        bar(x1,y1,x2-9,y2-9);
        setfillstyle(SOLID_FILL,BLACK);
        bar(x1+8,y2-8,x2,y2);
        bar(x2-8,y1+8,x2,y2);

        setcolor(MAGENTA);
        settextjustify(CENTER_TEXT,CENTER_TEXT);
        outtextxy(MidX-4,MidY-40,"MENU EXAMPLE");
        outtextxy(MidX-4,MidY-20,"IN GRAPHICS MODE");
        outtextxy(MidX-4,MidY+25,"6-1994 by");
        outtextxy(MidX-4,MidY+45,"X.Y.CAO");
        getch();

        putimage(x1,y1,Buffer,COPY_PUT);
        free(Buffer);
        settextjustify(LEFT_TEXT,TOP_TEXT);
    }
}

/* modified by meteor135
2005年5月21日 0:56:55*/
void MessageBox(char *Message)
{
    int MidX,MidY,x1,y1,x2,y2,size,Len;
    void *Buffer;

    MidX=(WindowMaxX-WindowMinX)/2;
    MidY=(WindowMaxY-WindowMinY)/2;
    Len=8*(strlen(Message)+1)/2;
    x1=MidX-Len-5*8;
    x2=MidX+Len+5*8;
    y1=MidY-50;
    y2=MidY+50;

    size=imagesize(x1,y1,x2,y2);
    if((Buffer=malloc(size))==NULL)
    {
        outtextxy(100,100,"Out of memorry! Press any key to continue.");
        getch();
    }
    else
    {
        getimage(x1,y1,x2,y2,Buffer);

        setcolor(AllColors[MenuEdge]);
        rectangle(x1,y1,x2-13,y2-13);

        setfillstyle(SOLID_FILL,AllColors[PopWindow]);
        bar(x1+1,y1+1,x2-14,y2-14); //2005年5月21日 0:51:14

        setfillstyle(SOLID_FILL,DARKGRAY);//2005年5月21日 0:56:37
        bar(x1+12,y2-12,x2,y2);
        bar(x2-12,y1+12,x2,y2);

        setcolor(MAGENTA);//2005年5月21日 0:56:26
        settextjustify(CENTER_TEXT,CENTER_TEXT);
        outtextxy(MidX,MidY-20,Message);

        setfillstyle(SOLID_FILL,LIGHTRED);
        bar(MidX-3*8,MidY+16,MidX+3*8,MidY+34);
        setcolor(YELLOW);
        outtextxy(MidX,MidY+26,"OK");

        getch();
        putimage(x1,y1,Buffer,COPY_PUT);
        free(Buffer);
        settextjustify(LEFT_TEXT,TOP_TEXT);
    }
}

void MoveText(void)
{
    int i;

    /* Clear window  */
    setfillstyle(SOLID_FILL,BLUE);
    bar(WindowMinX,WindowMinY,WindowMaxX,WindowMaxY);

    setcolor(YELLOW);
    for(i=300;i>1;i-=2)
    {
        outtextxy(i,100,"Menu example!");
        delay(50);
        bar(i,100,i+104,108);
    }
}

void GoodBye(char *pcInf1,char *pcInf2)
{
    int f;

    clrscr();
    window(1,1,80,1);
    textbackground(LIGHTBLUE);
    clrscr();

    highvideo();
    textcolor(WHITE);
    cprintf(pcInf1);
    textcolor(YELLOW);
    cprintf(pcInf2);
    window(1,1,80,25);
    printf("\n");

    for(f=400;f<800;f+=100)
    {
        sound(f);
        delay(100);
    }

    for(f=400;f>=200;f-=100)
    {
        sound(f);
        delay(200);
    }
    sound(1000);
    delay(1000);

    nosound();
    exit(0);
}

3 楼


修改的地方能注明一下吗???最好能解释修改的原因!!!
谢谢大虾!![em8][em8]

4 楼

为什么按原书建一个menu3.h头文件不行????

5 楼

Changed farmalloc to malloc and also changed farfree to free in function ExitMenu().
    Or else it will cause CPU error!
    2005年5月21日 0:30:48
    */
什么情况下可以用farmalloc,farfree????

我来回复

您尚未登录,请登录后再回复。点此登录或注册