C语言编写菜单示例

标签:
cprogramming杂谈 |
分类: C/CPP |
通过编写TurboC文本菜单这个例子,介绍如何用C语言编写文本菜单。其中一些函数和颜色的枚举类型只能在TurboC中运行,而在VC中无法使用,比如bioskey函数……
源程序:
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
char *Menu[] = {"File",
"Edit",
"Run",
"Compile",
"Project",
"Options",
"Debug",
"Break/watch"};
char *Prompt[] = {"F1-Help",
"F5-Zoom",
"F6-Switch",
"F7-Trace",
"F8-Step",
"F9-Make",
"F10-Menu",
"NUM"};
char *Menus[] = {"Load F3",
"Pick Alt-F3",
"New",
"Save F2",
"Write to",
"Driectory",
"Change dir",
"Os shell",
"Quit Alt-X",
"Run Ctrl-F9",
"Program reset Ctrl-F2",
"Go to Cursor F4",
"Trace into F7",
"Step over F8",
"User screen Alt-F5",
"Compile to OBJ",
"Make EXE File",
"Link EXE File",
"Build all",
"Primary C file:",
"Get info",
"Project name",
"Break make on Errors",
"Auto dependencies Off",
"Clear project",
"Remove messages",
"Compiler",
"Linker",
"Environment",
"Directories",
"Arguments",
"Save options",
"Retrieve options",
"Evaluate Ctrl-F4",
"Call stack Ctrl-F3",
"Find function",
"Refresh display",
"Display swapping Smart",
"Source debugging On",
"Add watch Ctrl-F7",
"Delete watch",
"Edit watch",
"Remove all watch",
"",
"Toggle breakpoint Ctrl-F8",
"Clear all breakpoints",
"View next breakpoint"};
int MnN[] = { 9, 0, 6, 6, 5, 7, 6, 8};
int MnLoc[][5] = {{4,3,2,18,12},
{11,0,0,0,0},
{18,17,2,42,9},
{24,23,2,57,9},
{34,33,2,69,8},
{44,43,2,62,10},
{54,45,2,79,9},
{62,50,2,79,11}};
int Mnm, Mns;
char buf[30*25*2], buf1[40*3*2];
void ShowMenuM (void);
void SetMenuM (int );
void ClrMenuM (int );
void ShowPrompt(void);
void ShowMenuS (int );
void HideMenuS (int );
void SetMenuS (int );
void ClrMenuS (int );
void SelLR (int );
void SelUD (int );
void ExeItem (int, int);
void ScanKb (int *, int *);
void main(void)
{
int i,idx,key0,key1,flag = 1;
textbackground(BLUE);
clrscr( );
ShowMenuM();
Mnm = 1;
Mns = 0;
SetMenuM(Mnm);
ShowPrompt();
while(flag){
key0=key1=0;
ScanKb(&key0, &key1);
if(key0 != 0){
if(Mns == 0){
if(key0 == 13)
ShowMenuS(Mnm);
else{
for(i=0;i<8;i++)
if(key0 - *Menu[i] == 0 || key0 - *Menu[i] == 32)
break;
if(i < 8)
ShowMenuS(i+1);
}
}
else{
if(key0 == 13)
ExeItem(Mnm,Mns);
else if(key0 == 27){
HideMenuS(Mnm);
Mns = 0;
}
else{
for(i=1,idx=0;i<Mnm;i++)
idx += MnN[i-1];
for(i=idx;i<idx+MnN[Mnm-1];i++)
if(key0 - *Menus[i] == 0 || key0 - *Menus[i] == 32)
break;
if(i < idx + MnN[Mnm-1])
ExeItem(Mnm,i - idx + 1);
}
}
}
else{
switch(key1){
case 33: ShowMenuS(1); break;
case 18: ShowMenuS(2); break;
case 19: ShowMenuS(3); break;
case 46: ShowMenuS(4); break;
case 25: ShowMenuS(5); break;
case 24: ShowMenuS(6); break;
case 32: ShowMenuS(7); break;
case 48: ShowMenuS(8); break;
case 61: ExeItem(1,1); break;
case 106:ExeItem(1,2); break;
case 60: ExeItem(1,4); break;
case 45: flag = 0; break;
case 102:ExeItem(3,1); break;
case 95: ExeItem(3,2); break;
case 62: ExeItem(3,3); break;
case 65: ExeItem(3,4); break;
case 66: ExeItem(3,5); break;
case 108:ExeItem(3,6); break;
case 97: ExeItem(7,1); break;
case 96: ExeItem(7,2); break;
case 100:ExeItem(8,1); break;
case 101:ExeItem(8,6); break;
case 72: SelUD(-1); break;
case 80: SelUD( 1); break;
case 75: SelLR(-1); break;
case 77: SelLR( 1); break;
}
}
}
}
void ShowMenuM(void)
{
int i;
window(1,1,80,1);
textbackground(WHITE);
textcolor(BLACK);
clrscr( );
for(i=0; i<8; i++){
gotoxy(MnLoc[i][0], 1);
textcolor(RED);
cprintf("%c", *Menu[i]);
textcolor(BLACK);
cprintf("%s", Menu[i]+1);
}
}
void SetMenuM(int mmn)
{
window(1,1,80,1);
textbackground(BLACK);
textcolor(WHITE);
gotoxy(MnLoc[mmn-1][0], 1);
cprintf("%s", Menu[mmn-1]);
}
void ClrMenuM(int mmn)
{
window(1,1,80,1);
textbackground(WHITE);
gotoxy(MnLoc[mmn-1][0], 1);
textcolor(RED);
cprintf("%c", *Menu[mmn-1]);
textcolor(BLACK);
cprintf("%s", Menu[mmn-1]+1);
}
void ShowPrompt(void)
{
int i;
window(1,25,80,25);
textbackground(WHITE);
textcolor(BLACK);
clrscr( );
for(i=0; i<6; i++){
textcolor(RED);
cprintf(" %c%c", *Prompt[i], *(Prompt[i]+1));
textcolor(BLACK);
cprintf("%s ", Prompt[i]+2);
}
textcolor(RED);
cprintf(" %c%c%c", *Prompt[i], *(Prompt[i]+1),
*(Prompt[i]+2));
textcolor(BLACK);
cprintf("%s ", Prompt[i]+3);
textbackground(BLUE);
textcolor(WHITE);
cprintf(" %s ", Prompt[7]);
}
void ShowMenuS(int mmn)
{
int i, left, top, right, bottom, ht, wd, idx;
if(mmn == Mnm && Mns
> 0)
return;
if(mmn != Mnm){
if(Mns>0 && Mnm !=
2) HideMenuS(Mnm);
ClrMenuM(Mnm);
SetMenuM(Mnm=mmn);
}
Mns = 1;
if(Mnm == 2)
return;
left = MnLoc[Mnm-1][1];
top = MnLoc[Mnm-1][2];
right = MnLoc[Mnm-1][3];
bottom = MnLoc[Mnm-1][4];
ht = bottom - top + 1;
wd = right - left + 1;
for(i=1,idx=0;i<Mnm;i++)
idx += MnN[i-1];
gettext(left, top, right, bottom, buf);
window (left, top, right, bottom);
textbackground(WHITE);
textcolor(BLACK);
clrscr( );
window (left, top, right, bottom + 1);
putch(0xda);
for(i=2;i<wd;i++)
putch(0xc4);
putch(0xbf);
for(i=2;i<ht;i++){
gotoxy(1,i);
textcolor(BLACK);
cprintf("%c %-*s%c", 0xb3, wd - 3, Menus[idx+i-2], 0xb3);
gotoxy(3,i);
textcolor(RED);
cprintf("%c", *Menus[idx+i-2]);
}
gotoxy(1,i);
textcolor(BLACK);
putch(0xc0);
for(i=2;i<=right-left;i++)
putch(0xc4);
putch(0xd9);
SetMenuS(Mns);
}
void HideMenuS(int mmn)
{
int left, top, right, bottom;
left = MnLoc[mmn-1][1];
top = MnLoc[mmn-1][2];
right = MnLoc[mmn-1][3];
bottom = MnLoc[mmn-1][4];
puttext(left, top, right, bottom, buf);
Mns = 0;
}
void SetMenuS(int smn)
{
int i, left, top, right, bottom, ht, wd, idx;
if(Mnm == 2)
return;
ClrMenuS(Mns);
Mns = smn;
left = MnLoc[Mnm-1][1];
top = MnLoc[Mnm-1][2];
right = MnLoc[Mnm-1][3];
bottom = MnLoc[Mnm-1][4];
wd = right - left + 1;
for(i=1,idx=0;i<Mnm;i++)
idx += MnN[i-1];
idx += Mns - 1;
window (left, top, right, bottom);
textbackground(BLACK);
textcolor(WHITE);
gotoxy(2,Mns+1);
cprintf(" %-*s", wd - 3, Menus[idx]);
}
void ClrMenuS(int smn)
{
int i, left, top, right, bottom, ht, wd, idx;
if(Mnm == 2)
return;
left = MnLoc[Mnm-1][1];
top = MnLoc[Mnm-1][2];
right = MnLoc[Mnm-1][3];
bottom = MnLoc[Mnm-1][4];
wd = right - left + 1;
for(i=1,idx=0;i<Mnm;i++)
idx += MnN[i-1];
idx += smn - 1;
window (left, top, right, bottom);
textbackground(WHITE);
textcolor(BLACK);
gotoxy(2,smn+1);
cprintf(" %-*s", wd - 3, Menus[idx]);
gotoxy(3,smn+1);
textcolor(RED);
cprintf("%c", *Menus[idx]);
}
void SelLR(int lr)
{
int mmn = Mnm + lr;
if(mmn > 8)
mmn = 1;
else if(mmn < 1)
mmn = 8;
if(Mns > 0)
ShowMenuS(mmn);
else{
ClrMenuM(Mnm);
SetMenuM(Mnm=mmn);
}
}
void SelUD(int ud)
{
int smn = Mns + ud;
if(Mnm == 2)
return;
if(smn > MnN[Mnm-1])
smn = 1;
else if(smn < 1)
smn = MnN[Mnm-1];
if(Mns == 0){
if(ud == 1) ShowMenuS(Mnm);
}
else{
if(Mnm == 8 && smn == 5)
if(ud > 0) smn++; else smn--;
ClrMenuS(Mns);
SetMenuS(Mns=smn);
}
}
void ExeItem(int mmn, int smn)
{
int i, key0, key1, ht, wd, idx;
if(mmn == 1 && smn == 9)
exit(0);
if(mmn == 2) return;
if(Mns > 0 && Mnm !=
2) HideMenuS(Mnm);
if(mmn != Mnm){
ClrMenuM(Mnm);
SetMenuM(Mnm=mmn);
}
Mns = 0;
for(i=1,idx=0;i<Mnm;i++)
idx += MnN[i-1];
idx += smn - 1;
ht = 3;
wd = 40;
gettext(21, 12, 60, 14, buf1);
window (21, 12, 60, 14);
textbackground(WHITE);
textcolor(BLACK);
clrscr( );
window (21, 12, 60, 14 + 1);
putch(0xda);
for(i=2;i<wd;i++)
putch(0xc4);
putch(0xbf);
for(i=2;i<ht;i++){
gotoxy(1,i);
cprintf("%c %-*s%c", 0xb3, wd - 3, "", 0xb3);
}
gotoxy(1,i);
putch(0xc0);
for(i=2;i<wd;i++)
putch(0xc4);
putch(0xd9);
textcolor(YELLOW);
gotoxy(3,2);
cprintf("Executing...(MMN=%d,SMN=%d), ESC return",mmn,smn);
do ScanKb(&key0, &key1); while(key0
!= 27);
puttext(21, 12, 60, 14, buf1);
}
void ScanKb(int *pk0, int *pk1)
{
int key;
ShowPrompt();
while (bioskey(1) == 0);
key = bioskey(0);
*pk0 = key & 0xff;
*pk1 = (key >> 8) &
0xff;
}
相关函数:
以下函数的原型都在conio.h中。
1、window函数:
原型:void window (int left, int top, int right, int bottom);
原型在conio.h中。
功能:创建矩形字符文本窗口。其左上角的坐标由left,top表示;右下角的坐标由right, bottom表示。
注意:一旦该函数调用成功,所有定位坐标都是相对于窗口,而非相对于屏幕。
2、clrscr函数
原型:void clrscr(void);
功能:清除当前字符窗口,将光标定位在左上角(1,1)处。
3、textbackground函数
原型:void textbackground(int newcolor);
功能:设置字符屏幕的背景颜色为newcolor。
4、textcolor函数
原型:void textcolor(int newcolor);
功能:设置字符屏幕下的字符颜色为newcolor。
颜色的枚举说明如下:
enum COLORS {
};
5、gotoxy函数
原型:void gotoxy(int x, int y);
功能:将字符屏幕的光标移动到x,y所指定的位置。如果其中有一个坐标值无效,则光标不移动。
6、gettext函数
原型:int gettext(int left, int top, int right, int bottom,void *buf);
功能:将左上角的坐标为(left,top),右下角的坐标为(right,bottom)矩形上的字符拷贝到由buf所指向的内存。
注意:
(1)坐标是屏幕绝对坐标,不是窗口的相对坐标。
(2)保存屏幕上一个区域所需要的内存数量可按照公式:rows′columns′2
原因是屏幕上每个字符要求两字节的存储单元,一个字节存放字符本身,另一个字节存放该字符的属性。
7、puttext函数
原型:int puttext(int left, int top, int right, int bottom,void * buf);
功能:将原来由gettext函数存储到buf所指向的内存中的字符拷贝到左上角的坐标为(left,top),右下角的坐标为(right,bottom)的矩形区域中。
注意:坐标是屏幕绝对坐标,不是窗口的相对坐标。
8、bioskey函数
原型:int bioskey(int cmd);
该函数原型在bios.h中。
功能:bioskey完成直接键盘操作。cmd的值决定执行什么操作。
如果cmd的值是0,bioskey返回下一个在键盘上键入的值(它将等待到按下下一个键)。它返回一个16位的二进制数,包括两个不同的值。当按下一个“普通键”时,它的低8位数存放着该字符的ASCII码。对于“特殊键”,低8位为0。特殊键包括箭头键,功能键,shift,Alt键等。高8位存放该键的扫描码。
当cmd的值是1时,bioskey查询是否已经按下一个键。当按下时,它返回它返回非0值;否则返回0。
例如:while(bioskey(1)==0);
key=bioskey(0);
key=key&0xff?0:key>>8;
if(key==45) exit(0);
if(key==30){
…
}
…
运行结果>>
http://s10/middle/96ea2f1b4b5630dc78b19&690
键盘编码表>>