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); }
гостевая; E-mail |