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('&#9484;');
  for( i=3; i<=width; i++)
	{ gotoxy(i,y);
	  putch('&#9472;');
	  gotoxy(i,y+height-1);
	  putch('&#9472;');
	};
  gotoxy(x+width-1,y);
  putch('&#9488;');
  for(i=2;i<height;i++)
  {
    gotoxy(x,i);
    putch('&#9474;');
    gotoxy(x+width-1,i);
    putch('&#9474;');
  }
  gotoxy(x,y+height-1);
  putch('&#9492;');
  gotoxy(x+width-1,y+height-1);
  putch('&#9496;');
}
 
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("&#9618;");
	  };
 
   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);
}

Рейтинг@Mail.ru

вверх гостевая; E-mail
Hosted by uCoz