Pers.narod.ru. Алгоритмы. Многоуровневое консольное меню на классах |
Демка одной из многочисленных возможных реализаций собственного консольного интерфейса на Си. При запуске будет выглядеть примерно так:

Вот полный листинг программы.
#include <conio.h>
#include <string.h>
#include <alloc.h>
#include <math.h>
#define W WHITE
#define B BLACK
#define GR GREEN
#define LG 7
#define LB LIGHTBLUE
enum keys{nothing=1000,Right,Left,Up,Down,Esc,Enter,F10};
class MEN
{ public:
char *name;
void (*func_ptr)(char *);
MEN *sub;
};
class WIN {
public:
char *name;
void (*func_ptr)(char *);
MEN *sub;
int left,
up,
right,
down;
unsigned size;
void *buf;
int main_choice(MEN *);
};
int level=0;
int color;
char *work;
int displ_x;
void draw_frame(int x,int y,int width,int height,
int attr_frame)//рисует рамку
{
int i;
textattr(attr_frame);
gotoxy(x,y);
putch('┌');
for( i=3; i<=width; i++)
{ gotoxy(i,y);
putch('─');
gotoxy(i,y+height-1);
putch('─');
};
gotoxy(x+width-1,y);
putch('┐');
for(i=2;i<height;i++)
{
gotoxy(x,i);
putch('│');
gotoxy(x+width-1,i);
putch('│');
}
gotoxy(x,y+height-1);
putch('└');
gotoxy(x+width-1,y+height-1);
putch('┘');
}
WIN *win_sav(int x,int y,int width,int height)//сохраняем содержимое окна
{
WIN *k;
void *dest;
unsigned s,s0;
s0=(width+1)*(height+1)*2;
s=sizeof(WIN)+2;
k=(WIN *)malloc(s);
dest=(void *)malloc(s0);
gettext(x,y,x+width,y+height,dest);
k->left=x;
k->up=y;
k->right=width+x;
k->down=height+y;
k->buf=dest;
k->size=s+s0;
return(k);
}
void win_close(WIN *k)
{
void *dest;
if(k!=NULL)
{
dest=k->buf;
puttext(k->left,k->up,k->right,k->down,k->buf);
free((void *)k);
free(dest);
}
}
WIN *win_open(int x,int y,int width,int height,//save window,рисует новое
int back_col,int frame_col)//обрамляет его
{
void draw_frame(int x,int y,int width,int height,
int attr_frame);
int attr_frame;
WIN *w;//указатель на сохранённое окно
attr_frame=frame_col+16*back_col;
w=win_sav(x,y,width+1,height);
window(x,y,x+width-1,y+height-1);
textattr(attr_frame);
clrscr();
draw_frame(2,1,width-2,height,attr_frame);
return(w);
}
int key_pressed(void)//считывает символ
{
char key;
if(!(key=getch()))//????/
{ key=getch();
switch(key)
{
case 77:return Right;
case 75:return Left;
case 72:return Up;
case 80:return Down;
case 68:return F10;
default:return key;
}
}
else
switch(key)
{
case 27:return Esc;
case 13:return Enter;///???
default:return key;
}
}
int WIN::main_choice(MEN *m)
{
int sub_choice(int x,int y,int back_col,int text_col,int frame_col,MEN *m) ;
void stroka(char *name, int mark);
int hot_key,width=0,puncts=0,key=0,mov_y;
MEN *s=m;
char c;
displ_x=2; //смещ. по Х
mov_y=1; //смещ. по У
level=0;
while( s->name!=NULL )
{
width+=strlen(s->name);
++puncts;++s;
};
width+=15;
window(1,1,80,1);
textbackground(LG);
clrscr(); //веpхняя стpока
s=m;
gotoxy(displ_x,mov_y);
textattr(B+16*LG);//????
for(int j=0;j<puncts;j++)
{
cprintf("%s",s->name); cputs(" ");
++s;
}; //нарисовали заголовки
s=m;
textattr(W+16*GR);
gotoxy(displ_x,mov_y);
cprintf("%s",s->name);
stroka(s->name,2);
window(1,1,80,1);
hot_key=0;
while(1)
{
key=0;
if(!hot_key) key=key_pressed();
switch (key+hot_key)
{
case Enter:if(s->sub)
{ level=1;
hot_key=sub_choice(displ_x,mov_y+1,
LG,B,BLUE, s->sub);
stroka(s->name,2);
window(1,1,80,1);
}
break;
case Right:
case Left:
textattr(B+16*LG);
gotoxy(displ_x,mov_y);
cprintf("%s",s->name);
switch(key+hot_key)
{
case Right:if((++s)->name!=NULL)displ_x=wherex()+3;
else
{
displ_x=2;
s=m;
};
break;
case Left:if(s!=m)
{
--s;
displ_x=displ_x-strlen(s->name)-3;
if(displ_x<=0)++displ_x;
}
else
{
s=&m[puncts-1];
displ_x=width-strlen(s->name);
}
break;
}
gotoxy(displ_x,mov_y);
textattr(W+16*GR);
cprintf("%s",s->name);//
if(!level)stroka(s->name,0);//if из 1-го ур-ня
window(1,1,80,1);
if((level)&&(s->sub))
{ level=0;
stroka(s->name,0);
level=1;
hot_key=sub_choice(displ_x,mov_y+1,
LG,B,BLUE,s->sub);
stroka(s->name,2);
window(1,1,80,1);
}
else hot_key=0;
break;
case F10:
case Esc:
return(Esc);
}// switch
}// for(;;)
}
int sub_choice(int x,int y,int back_col,int text_col,int frame_col,MEN *m)
{
void stroka(char *name, int mark);
int hot_key,key,puncts=0,height,width=0,len=0,mov_x,mov_y;
MEN *s=m;
WIN *win;
mov_x=3;
mov_y=2;
char c;
while(s->name!=NULL)//считаем ширину
{
len=strlen(s->name)-1;
if(width<len)width=len;
++puncts;++s;
}
height=puncts+2;//определяем высоту
win=win_open(x-1, y, width+7, height,
back_col,frame_col); //обращается к сохранению окна и рисует
//его + рамка
s=m;
textattr(text_col+16*back_col);
for(int j=0;j<puncts;j++)
{
gotoxy(mov_x,mov_y);
cprintf("%s",s->name);
++s;++mov_y;
}
s=m;
textattr(W+16*GR);
mov_y=2;
gotoxy(mov_x,mov_y);
cprintf("%s",s->name);
stroka(s->name,2);
window(win->left,win->up,win->right,win->down);
hot_key=0;
while(1)
{
gotoxy(mov_x,mov_y);
key=0;
if(!hot_key) key=key_pressed();
switch(key+hot_key)
{
case Esc: --level;
// stroka(s->name,1);
win_close(win);
return(0);
case Enter:if(s->sub)
{
++level;
hot_key=sub_choice(displ_x+strlen(s->name)-1
,mov_y+2,
back_col,text_col,frame_col,
s->sub);
window(win->left,win->up,
win->right,win->down);
}
else {
(*(s->func_ptr))(s->name);//вызов функции
//данного меню
window(win->left,win->up,win->right,win->down);
}
break;
case Up:
case Down:textattr(text_col+16*back_col);
cprintf("%s",s->name);
textattr(W+16*B);
switch(key+hot_key)
{
case Down:if((++s)->name!=NULL)++mov_y;
else
{
mov_y=2;
s=m;
}
break;
case Up:if(s!=m)
{
--mov_y;
--s;
}
else
{
mov_y=puncts+1;
s=&m[puncts-1];
}
}
gotoxy(mov_x,mov_y);
textattr(W+16*GR);
cprintf("%s",s->name);
stroka(s->name,0);
window(win->left,win->up,
win->right,win->down);
break;
case Right:
case Left: win_close(win);level=1;return(hot_key+key);
case F10:
--level;win_close(win);return(F10);
}
}
}
void mn_func(char *punct)
{
WIN *wn;
wn=win_open(25,15,30,4,/*LG*/0,/*W*/10);
gotoxy(4,2);
cprintf(" Вызвана функция меню ");
gotoxy(int (30-strlen(punct))/2,3);
cprintf("%s",punct);
getch();
win_close(wn);
}
void presentaz()
{
WIN *mywin;
mywin=win_open(20,3,40,19,0,10);
gotoxy(11,4);
cprintf("программу разработал");
gotoxy(12,8);
cprintf("такой-то ");
gotoxy(3,11);
cprintf(" впиши здесь");
gotoxy(7,16);
cprintf(" себя и еще кого-то ");
gotoxy(7,18);
cprintf(" Фамилия Имя ");
getch();
win_close(mywin);
}
void stroka(char *name, int mark) //динамическая строка
// mark=0 -> заменить
// 1 стереть
// 2 добавить
{ static point_new=1;
static point_pred=1;
int len;
window(1,23,80,23);
textattr(B+16*LG);
len=strlen(name);
switch(mark)
{
case 0:{ if(!level)
point_pred=1;
for(int i=point_pred;i<=79;i++)
{ gotoxy(i,1);
cprintf(" ");
}
gotoxy(point_pred,1);
cprintf("\\%s",name);
if(name[len-1]=='') { gotoxy(point_pred+len-1,1);
cprintf(" ");
len-=1;
};
point_new=point_pred+len+1;
for(i=point_new;i<=15;i++)
{ gotoxy(i,1);
cprintf(" ");
}
break;
};
case 1:{ for(int i=point_pred;i<=79;i++)
{ gotoxy(i,1);
cprintf(" ");
};
point_new=point_pred;
point_pred=1;
break;
};
case 2:{gotoxy(point_new,1);
cprintf("\\%s",name);
if(name[len-1]=='') { gotoxy(point_new+len-1,1);
cprintf(" ");
len-=1;
};
point_pred=point_new;
point_new+=strlen(name)+1;
break;
}
}
}
void drow_1st_screen (void)
{
textbackground(LG);//цвет фона для текста(светло-серый)
clrscr();
textcolor(LB);//цвет символов в текстовом режиме(светло-синий)
for(int i=1; i<=80; i++)//столбцы
for(int j=2; j<=22; j++)//строки
{gotoxy(i,j);
cprintf("▒");
};
gotoxy(2,24);
textcolor(RED);
cprintf("F10 , Esc ");
textcolor(B);
cprintf("Выход");
textcolor(LB);
window(1,25,80,25);//устанавливает активное окно в текстовом режиме
//(лев,верх,право,низ)
textbackground(B);
clrscr();
textcolor(W);
cprintf("\\Строка помощи программы");
}
void main(void)
{
void drow_1st_screen (void);
MEN mn_5_2[] ={
{" Меню 5.2.1 ",&mn_func,0},
{" Меню 5.2.2 ",&mn_func,0},
{NULL,NULL,0}
};
MEN mn_5[] ={
{" Меню 5.1 ",&mn_func,0},
{" Меню 5.2 ",0,mn_5_2},
{NULL,NULL,0}
};
MEN mn_4_1[] ={
{" Меню 4.1.1 ",&mn_func,0},
{" Меню 4.1.2 ",&mn_func,0},
{" Меню 4.1.3 ",&mn_func,0},
{NULL,NULL,0}
};
MEN mn_4_2[] ={
{" Меню 4.2.1 ",&mn_func,0},
{" Меню 4.2.2 ",&mn_func,0},
{" Меню 4.2.3 ",&mn_func,0},
{NULL,NULL,0}
};
MEN mn_4_5[] ={
{" Меню 4.5.1 ",&mn_func,0},
{" Меню 4.5.2 ",&mn_func,0},
{" Меню 4.5.3 ",&mn_func,0},
{NULL,NULL,0}
};
MEN mn_4[] ={
{" Меню 4.1 ",0,mn_4_1},
{" Меню 4.2 ",0,mn_4_2},
{" Меню 4.3 ",&mn_func,0},
{" Меню 4.4 ",&mn_func,0},
{" Меню 4.5 ",0,mn_4_5},
{NULL,NULL,0}
};
MEN mn_3_1[]={
{" Меню 3.1.1 ",&mn_func,0},
{" Меню 3.1.2 ",&mn_func,0},
{" Меню 3.1.3 ",&mn_func,0},
{NULL,NULL,0}
};
MEN mn_3_2[]={
{" Меню 3.2.1 ",&mn_func,0},
{" Меню 3.2.2 ",&mn_func,0},
{" Меню 3.2.3 ",&mn_func,0},
{" Меню 3.2.4 ",&mn_func,0},
{" Меню 3.2.5 ",&mn_func,0},
{NULL,NULL,0}
};
MEN mn_3[] ={
{" Меню 3.1 ",NULL,mn_3_1},
{" Меню 3.2 ",NULL,mn_3_2},
{" Меню 3.3 ",&mn_func,0},
{NULL,0,0}
};
MEN mn_2_3[]={
{" Меню 2.3.1 ",&mn_func,0},
{" Меню 2.3.2 ",&mn_func,0},
{" Меню 2.3.3 ",&mn_func,0},
{NULL,NULL,0}
};
MEN mn_2_4[]={
{" Меню 2.4.1 ",&mn_func,0},
{" Меню 2.4.2 ",&mn_func,0},
{" Меню 2.4.3 ",&mn_func,0},
{" Меню 2.4.4 ",&mn_func,0},
{NULL,NULL,0}
};
MEN mn_2_6[]={
{" Меню 2.6.1 ",&mn_func,0},
{" Меню 2.6.2 ",&mn_func,0},
{" Меню 2.6.3 ",&mn_func,0},
{NULL,NULL,0}
};
MEN mn_2[] ={
{" Меню 2.1 ",&mn_func,0},
{" Меню 2.2 ",&mn_func,0},
{" Меню 2.3 ",NULL,mn_2_3},
{" Меню 2.4 ",NULL,mn_2_4},
{" Меню 2.5 ",&mn_func,0},
{" Меню 2.6 ",NULL,mn_2_6},
{NULL,NULL,0}
};
MEN mn_1_1[]={
{" Меню 1.1.1 ",&mn_func,0},
{" Меню 1.1.2 ",&mn_func,0},
{NULL,NULL,0}
};
MEN mn_1_2[]={
{" Меню 1.2.1 ",&mn_func,0},
{" Меню 1.2.2 ",&mn_func,0},
{" Меню 1.2.3 ",&mn_func,0},
{" Меню 1.2.4 ",&mn_func,0},
{NULL,NULL,0}
};
MEN mn_1[]={
{" Меню 1.1 ",NULL,mn_1_1},
{" Меню 1.2 ",NULL,mn_1_2},
{NULL,0,0}
};
MEN main_mn[] = {
{" Меню 1 ",0, mn_1},
{" Меню 2 ",0, mn_2},
{" Меню 3 ",0, mn_3},
{" Меню 4 ",0, mn_4},
{" Меню 5 ",0, mn_5},
{NULL,0,0}
};
WIN ww;
_setcursortype(_NOCURSOR);//тип курсора(отключить)
drow_1st_screen() ;
presentaz(); //вставить таблицу
ww.main_choice(main_mn);
window(1,1,80,25);
textbackground(B);
clrscr();
_setcursortype(_NORMALCURSOR);
}
|
|