📄 menu.cpp
字号:
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <stdlib.h>
#include <myfunc.h>
#include <key.h>
#include <menu.h>
/*Marco Definitions*/
/*///////////////////////////////////////////////*/
PMI FindMI(PSM sm,PMI mi);
PMI FindByKey(PSM sm,word key);
PMI FirstMI(PSM sm);
PMI LastMI(PSM sm);
PSM FirstSM();
PSM LastSM();
PSM FindSM(PSM sm);
void Bar(int x,int y,int len);
void UnBar(int x,int y,int len);
void PrintMI(PSM sm,PMI mi);
void UnselectSM(PSM sm);
void PutName(char *n);
/*///////////////////////////////////////////////*/
/*Gobal Variables*/
void VOID(){}
TMenu Menu={0,NULL,NULL};
int MenuBack=BLACK;
int SMSelBack=BLACK;
int SMSel=WHITE;
int MenuKey=YELLOW;
int SMBox=RED;
int SMBoxBack=WHITE;
int BarBack=BLUE;
int BarNor=BLACK;
int DisableColor=CYAN;
int MAXSM=20;
int MAXMI=100;
/*///////////////////////////////////////////////*/
PMI FindMI(PSM sm,PMI mi){
PMI t=sm->MIS;
while(t)
if(t->ShortKey==mi->ShortKey||t->KeyCode==mi->KeyCode) return t;
else t=t->Next;
return t;
}
/*///////////////////////////////////////////////*/
PMI FindByKey(PSM sm,word key){
PMI t=sm->MIS;
int n=sm->MIN;
while(n--)
if(t->ShortKey==key||t->KeyCode==toupper(key&0x00ff)) return t;
else t=t->Next;
return NULL;
}
/*///////////////////////////////////////////////*/
PSM FindSM(PSM sm){
PSM t=Menu.SMS;
while(t)
if(t->ShortKey==sm->ShortKey||t->KeyCode==sm->KeyCode) return t;
else t=t->Next;
return NULL;
}
/*///////////////////////////////////////////////*/
void Bar(int x,int y,int len){
struct text_info old;
gettextinfo(&old);
textbackground(BarBack);
gotoxy(x,y);
while(len--) putch(' ');
textattr(old.attribute);
}
/*///////////////////////////////////////////////*/
void UnBar(int x,int y,int len){
gotoxy(x,y);
while(len--) putch(' ');
}
/*///////////////////////////////////////////////*/
PMI NewMI(char *n,word sk,word hc,char *hint,void (*act)(),PSM sm){
PMI t=(PMI)malloc(sizeof(TMI));
if(t){
strcpy(t->Name,n);
t->ShortKey=sk;
t->HlpCtx=hc;
t->Hint=hint;
t->Action=act;
t->State=ENABLE;
t->Prev=t->Next=NULL;
t->SM=sm;
{ char *p=n; while(*p!='&'&&*p) p++; t->KeyCode=*(p+1);}
}
return t;
}
/*///////////////////////////////////////////////*/
PSM NewSM(int x,int y,int len,char *n,word sk,word hc){
PSM t=(PSM)malloc(sizeof(TSM));
if(t){
strcpy(t->Name,n);
t->X=x;t->Y=y;
t->ShortKey=sk;
t->HlpCtx=hc;
t->Len=len;
t->R.A.X=x-1;
t->R.A.Y=y+1;
t->R.B.X=x+len;
t->R.B.Y=y+2;
t->MIN=0;
t->MIS=t->CurMI=NULL;
t->Prev=t->Next=NULL;
{ char *p=n;while(*p!='&'&&*p) p++; t->KeyCode=*(p+1);}
}
return t;
}
/*///////////////////////////////////////////////*/
void AddMI(PSM sm,PMI mi){
InsMI(sm,1000,mi); /* It won't exceed 1000 MIS :)*/
}
/*///////////////////////////////////////////////*/
void InsMI(PSM sm,byte before,PMI mi){
PMI t=sm->MIS;
if(sm->MIN==MAXMI) return;
if(FindMI(sm,mi)!=NULL) return;
if(sm->MIS==NULL){
sm->MIS=sm->CurMI=mi;
sm->MIN=1;
sm->R.B.Y++;
sm->CurMI=mi;
return;
}
while((t->Next!=NULL)&&(before--)) t=t->Next;
sm->MIN++;
sm->R.B.Y++;
mi->Next=t->Next;
mi->Prev=t;
if(t->Next) t->Next->Prev=mi;
t->Next=mi;
}
/*///////////////////////////////////////////////*/
void AddSM(PSM sm){
InsSM(100,sm);
}
/*///////////////////////////////////////////////*/
void InsSM(int before,PSM sm){
PSM t=Menu.SMS;
if(Menu.SMN==MAXSM) return;
if(FindSM(sm)!=NULL) return;
Menu.SMN++;
if(Menu.SMS==NULL){
Menu.SMS=Menu.CurSM=sm;
return;
}
while(t->Next&&before--) t=t->Next;
sm->Next=t->Next;
if(t->Next) t->Next->Prev=sm;
t->Next=sm;
sm->Prev=t;
t=t->Next;
while(t) {
t->X+=strlen(sm->Name)+3;
t->R.A.X+=strlen(sm->Name)+3;
t->R.B.X+=strlen(sm->Name)+3;
t=t->Next;
}
}
word GetKey(){
while(!bioskey(1));
return bioskey(0);
}
/*///////////////////////////////////////////////*/
void DelMI(PSM sm,PMI mi){
PMI t;
if((t=FindMI(sm,mi))==NULL) return;
if(t==sm->CurMI) sm->CurMI=t->Prev;
sm->MIN--;
sm->R.B.Y--;
if(t->Next) t->Next->Prev=t->Prev;
if(t->Prev) t->Prev->Next=t->Next;
free(t);
}
/*///////////////////////////////////////////////*/
void DelSM(PSM sm){
PSM t,p;
int len;
if((t=FindSM(sm))==NULL) return;
if(t==Menu.CurSM) Menu.CurSM=t->Prev;
Menu.SMN--;
len=strlen(t->Name)+3;
p=t->Next;
free(t);
while(p){
p->R.A.X-=len;
p->R.B.X-=len;
p=p->Next;
}
}
/*///////////////////////////////////////////////*/
PMI FirstMI(PSM sm){ return sm->MIS;}
/*///////////////////////////////////////////////*/
PMI LastMI(PSM sm){
PMI t=sm->MIS;
while(t->Next) t=t->Next;
return t;
}
/*///////////////////////////////////////////////*/
PSM FirstSM(){ return Menu.SMS;}
/*///////////////////////////////////////////////*/
PSM LastSM(){
PSM T=Menu.SMS;
while(T->Next) T=T->Next;
return T;
}
/*///////////////////////////////////////////////*/
void EnableMI(PMI mi){
mi->State=ENABLE;
}
/*///////////////////////////////////////////////*/
void EnableSM(PSM sm){
sm->State=DISABLE;
}
/*///////////////////////////////////////////////*/
void DisableSM(PSM sm){
sm->State=DISABLE;
}
/*///////////////////////////////////////////////*/
void DisableMI(PMI mi){
mi->State=ENABLE;
}
/*///////////////////////////////////////////////*/
void SelectSM(PSM sm){
int i,Cur;
PMI t;
word Key;
struct text_info old;
gettextinfo(&old);
HideCursor();
if(sm==NULL) goto ret;
sm->Buffer=(char*)malloc((sm->R.B.X-sm->R.A.X)*(sm->R.B.Y-sm->R.A.Y)*2);
if(sm->Buffer==NULL) return;
gettext(sm->R.A.X,sm->R.A.Y,sm->R.B.X,sm->R.B.Y,sm->Buffer);
textbackground(MenuBack); textcolor(SMSel);
gotoxy(sm->X,sm->Y);
PutName(sm->Name);
textcolor(SMBox); textbackground(SMBoxBack);
Rectangle(sm->R.A.X,sm->R.A.Y,sm->R.B.X,sm->R.B.Y);
window(sm->R.A.X+1,sm->R.A.Y+1,sm->R.B.X-1,sm->R.B.Y-1);
textbackground(BLACK);
textcolor(YELLOW);
clrscr(); /*Is here OK!:)*/
window(1,1,80,25);
for(t=sm->MIS,i=1;i<=sm->MIN;t=t->Next,i++){
gotoxy(sm->R.A.X+1,sm->R.A.Y+i);
if(t==sm->CurMI) Cur=sm->R.A.Y+i;
PrintMI(sm,t);
}
Bar(sm->R.A.X+1,Cur,sm->Len);
textbackground(BarBack);
gotoxy(sm->R.A.X+1,Cur);
PutName(sm->CurMI->Name);
textbackground(BLACK);
if(sm->CurMI->Hint!=NULL) Hint(sm->CurMI->Hint);
textbackground(BLACK);
while(1){
if(sm->CurMI->Name[0]=='\\')
Hint(" ");
Key=GetKey();
if(Key==kbEsc) { UnselectSM(sm);goto ret;}
switch(Key){
case kbUp: UnBar(sm->R.A.X+1,Cur,sm->Len);
gotoxy(sm->R.A.X+1,Cur);
PrintMI(sm,sm->CurMI);
ag: Cur=Cur==sm->R.A.Y+1?sm->MIN+sm->R.A.Y:Cur-1;
sm->CurMI=sm->CurMI->Prev!=NULL?sm->CurMI->Prev:LastMI(sm);
gotoxy(sm->R.A.X+1,Cur);
if(sm->CurMI->Name[0]=='\\') goto ag;
Bar(sm->R.A.X+1,Cur,sm->Len);
gotoxy(sm->R.A.X+1,Cur);
textbackground(BarBack);
PrintMI(sm,sm->CurMI);
textbackground(BLACK);
if(sm->CurMI->Name[0]!='\\') Hint(sm->CurMI->Hint);
break;
case kbDown: UnBar(sm->R.A.X+1,Cur,sm->Len);
gotoxy(sm->R.A.X+1,Cur);
PrintMI(sm,sm->CurMI);
textbackground(BLACK);
ag1: Cur=Cur==sm->MIN+sm->R.A.Y? sm->R.A.Y+1:Cur+1;
sm->CurMI=sm->CurMI->Next!=NULL? sm->CurMI->Next:FirstMI(sm);
gotoxy(sm->R.A.X+1,Cur);
if(sm->CurMI->Name[0]=='\\') goto ag1;
Bar(sm->R.A.X+1,Cur,sm->Len);
gotoxy(sm->R.A.X+1,Cur);
textbackground(BarBack);
PrintMI(sm,sm->CurMI);
textbackground(BLACK);
if(sm->CurMI->Name[0]!='\\') Hint(sm->CurMI->Hint);
break;
case kbEnter:
Hint(" ");
if(sm->CurMI->Name[0]=='\\') break;
if(sm->CurMI->Name[0]=='\\') break;
if(sm->CurMI->SM!=NULL) SelectSM(sm->CurMI->SM);
else {
UnselectSM(sm);(*sm->CurMI->Action)();
}
goto ret;
case kbLeft: if(sm->CurMI->Name[0]=='\\') break;
Hint(" ");
UnselectSM(sm);
Menu.CurSM=Menu.CurSM->Prev==NULL?LastSM():Menu.CurSM->Prev;
SelectSM(Menu.CurSM);goto ret;
case kbRight:
Hint(" ");
if(sm->CurMI->Name[0]=='\\') break;
UnselectSM(sm);
Menu.CurSM=Menu.CurSM->Next==NULL?FirstSM():Menu.CurSM->Next;
SelectSM(Menu.CurSM);goto ret;
default: t=FindByKey(sm,Key);
if(t!=NULL){
UnselectSM(sm);
(t->Action)();
goto ret;
}
}
}
ret:
ShowCursor();
RESTORE
}
/*///////////////////////////////////////////////*/
void PrintMI(PSM sm,PMI mi){
int num=sm->Len;
struct text_info old;
gettextinfo(&old);
if(mi->State==DISABLE) textcolor(DisableColor);
if(mi->Name[0]=='\\') while(num--) putch(196);
else PutName(mi->Name);
if(mi->State==DISABLE) textattr(old.attribute);
}
/*///////////////////////////////////////////////*/
void UnselectSM(PSM sm){
if(sm==NULL||sm->Buffer==NULL) return;
gotoxy(sm->X,sm->Y);
PutName(sm->Name);
puttext(sm->R.A.X,sm->R.A.Y,sm->R.B.X,sm->R.B.Y,sm->Buffer);
}
/*///////////////////////////////////////////////*/
void PutName(char *n){
struct text_info old;
gettextinfo(&old);
while(*n)
if(*n=='&'){
textcolor(RED);
putch(*(n+1));
n+=2;
textattr(old.attribute);
}
else putch(*n++);
}
/*///////////////////////////////////////////////*/
void MenuDraw(){
PSM p=Menu.SMS;
while(p){
gotoxy(p->X,p->Y);
PutName(p->Name);
p=p->Next;
}
}
PSM HaveShortKey(word key){
PSM t=Menu.SMS;
while(t)
if(t->ShortKey==key) return t;
else t=t->Next;
return NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -