
C_Kurs_Lekt / C_III_семестр / 16-2_Горизонтальное_меню
.pdf
Горизонтальное меню
// Эта проãрамма - пример всплывающеãо меню ãоризонтальноãо
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<bios.h>
#include<ctype.h>
#include<string.h>
#include<dos.h>
#define VID_MEM ( ( char far* ) ( 0xB8000000L ) )
void draw_border(int , int , int , int , int, int, int);
void display_menu_gor(char *[], int , int ,int, int *, int, int, int );
void put_color_text(int ,int ,char *, int );
int user_case_gor(int , int , int , int *, char *[], char *, int, int, int);
int popupgor( char *[],char *, int , int, int, int, int, int, int); int is_in(char *, char );
void clskbr(void);
void vrest( int , int , int , int , const char far * ); void vsave( int , int , int , int , char far * );
void main(){
int vibor, i,j,c, col;
char *menu_name1[] = { "ВЫБОР ФУНКЦИИ 1", "Выбор №2", "ТРЕТИЙ ПУНКТ МЕНЮ", "ВЫХОД" };
clrscr(); c=32; col=1;
for(i=1; i<=25; i++) for(j=1; j<=80; j++,c++){
if(c>255) c=32; if(col>15) col=1;
if(i!=25 && j!=80) {textcolor(col); putch(c);}
}
do {
_setcursortype(_NOCURSOR);
vibor=popupgor( menu_name1, "0123", 4, 3, 3, 2, 8, 0, 15); _setcursortype(_NORMALCURSOR);
gotoxy(10,23); cprintf("Пользователь выбрал пóнêт %d", vibor);
getch();
}
while(vibor != -1);
}
1

/* высвечивание меню в óêазанном месте */
void display_menu_gor(char *menu[], int x, int y,int count, int *menuXpos,
int bord, int tcolor, int
foncolor) {
unsigned char b[][3] = { { 32, 32, 32 },
{
194, 179, 193 },
{
203, 186, 202 } }; int i;
struct text_info ti; char oldatr; gettextinfo(&ti); oldatr=ti.attribute; textcolor(tcolor); textbackground(foncolor);
for(i=0;i<count;i++){
gotoxy(menuXpos[i],y);
cputs(menu[i]); if ( i<count-1) {
gotoxy(menuXpos[i+1]-2,y-1); putch(b[bord][0]); gotoxy(menuXpos[i+1]-2,y); putch(b[bord][1]); gotoxy(menuXpos[i+1]-2,y+1); putch(b[bord][2]);
}
}
textattr(oldatr);
}
void draw_border(int x1, int y1, int x2, int y2,
int bord, int linecolor, int
foncolor) {
//Фóнêция обводит рамêою прямоóãольнóю область
//void draw_border(int x1, int y1, int x2, int y2, int color)
//можно добавить цвет (необходимо бóдет заменить putchar на putch )
//можно добавить выбор типа рамêи: 0 - нет; 1 - одинарная; 2 - двойная
unsigned char b[][6] = { { 32, 32, 32, 32, 32, 32 },
{
196, 179, 218, 192, 191, 217 },
{
205, 186, 201, 200, 187, 188 } }; struct text_info ti;
char oldatr; int i, j;
gettextinfo(&ti);
oldatr=ti.attribute;
textcolor(linecolor);
textbackground(foncolor);
2

for(i=x1+1;i<x2;i++) { gotoxy(i,y1); putch(b[bord][0]); gotoxy(i,y2); putch(b[bord][0]);
}
for(i=y1+1;i<y2;i++) { gotoxy(x1,i); putch(b[bord][1]); for(j=x1+1;j<x2;j++) {
gotoxy(j,i);
putch(32);
}
gotoxy(x2,i);
putch(b[bord][1]);
}
gotoxy(x1,y1); putch(b[bord][2]); gotoxy(x1,y2); putch(b[bord][3]); gotoxy(x2,y1); putch(b[bord][4]); gotoxy(x2,y2); putch(b[bord][5]);
textattr(oldatr);
}
//вывод теêстовой строêи óêазанным цветом и фоном с восстановлением
//прежних атрибóтов теêста
void put_color_text(int x,int y,char *p, int attrib) { struct text_info ti;
char oldatr; gettextinfo(&ti); oldatr=ti.attribute; textattr(attrib); gotoxy(x,y); cputs(p); textattr(oldatr);
}
/* ввести выбор пользователя */
user_case_gor(int x, int y, int count, int *menuXpos, char *menu[], char *keys,int tcolor, int foncolor,
int usercolor) {
union inkey { // объединение для "поддержêи" bioskey т.е. INT 16 char ch[2]; // младший и старший байты
int i; // слово целиêом
} c;
int arrow_choice=0,key_choice, textatuser, textatmenu;
/* осветить первый выбор */ gotoxy(x,y);
textatuser = usercolor + (foncolor<<4); textatmenu = tcolor + (foncolor<<4);
put_color_text(menuXpos[arrow_choice],y,menu[0], textatuser); //
Подсвеченный пóнêт clskbr();
for(;;) {
while(!bioskey(1)); /* ждать нажатия */ c.i=bioskey(0); // взять êод из бóфера êлавиатóры
3

/* вернóть выбор в номальный режим */ gotoxy(arrow_choice,y); put_color_text(menuXpos[arrow_choice],y,
menu[arrow_choice], textatmenu);
if(c.ch[0]) { /* обычная êлавиша */ key_choice= is_in(keys,tolower(c.ch[0])); if(key_choice) return key_choice-1; switch(c.ch[0]) {
case '\r' : return arrow_choice;
case 27 : return -1; /* выйти из меню */
}
}
else { /* специальная êлавиша */ switch(c.ch[1]) {
case 75 : arrow_choice--; break;/* стрелêа вниз
*/
case 77 : arrow_choice++; break;/* стрелêа вверх
*/
}
}
if(arrow_choice==count) arrow_choice=0; if(arrow_choice<0) arrow_choice=count-1;
/* подсветить выбраннóю опцию */ gotoxy(menuXpos[arrow_choice],y); put_color_text(x,y+arrow_choice,menu[arrow_choice],
put_color_text(menuXpos[arrow_choice],y,menu[arrow_choice], textatuser);
}
}
/* Фóнêция is_in() возвращает позицию "ãорячей" êлавиши в строêе. Если пользователь нажал не êлючевóю êлавишó,
то is_inвозвращает 0. */ int is_in(char *s, char c){
int i;
for(i=0; *s; i++)
if(*s++ == c) return i+1; return 0;
}
// Очистêа бóфера êлавиатóры
void clskbr( void )
{
asm {
PUSH ES;
XOR AX , AX;
CLI;
MOV ES , AX;
MOV AX , ES:[41Ah];
MOV ES:[41Ch] , AX;
STI;
POP ES;
4

};
}
/* вывести исчезающее меню и вернóть выбор возвращает -2, если меню не может быть создано
возвращает -1, если пользователь нажал êлавишó ESC в остальных слóчаях она возвращает номер выбранной альтернативы, начиная с 0 */
int popupgor( char *menu[],char *keys, int count, int x, int y, int border,
|
|
int tcolor, int foncolor, int usercolor |
) |
// |
char *menu[]; |
теêст меню |
|
// |
char *keys; |
ãорячие êлавиши |
//int count; число альтернатив (пóнêтов меню)
// |
int x,y; |
êоординаты левоãо верхнеãо óãла |
//int border; если 0 то без рамêи
//int tcolor; цвет теêста меню и рамêи
// |
int foncolor; |
цвет фона |
// |
int usercolor; |
цвет подсвеченноãо пóнêта |
{ |
|
|
int i,len;
int endx, endy, choice, *menuXpos; unsigned char *buffer;
if((x>80)||(x<1)||(y>25)||(y<1)) { printf(" выход за пределы эêрана"); return -2;
}
menuXpos=(int *)calloc(count, 1);
if(!menuXpos) exit(1); /* Вы можете здесь сами обработать ошибêó
*/
/* вычисление размеров */ len=0; for(i=0;i<count;i++) {
menuXpos[i]= x + len + 2; len += strlen(menu[i])+3; }
endx= x + len; endy= y + 2;
if(( endx > 80) || ( endy > 25)) { printf(" выход за пределы эêрана"); return -2;
}
/* размещение памяти для видео бóфера */
buffer=(unsigned char *)calloc((endx-x+1)*(endy-y+1), 2);
//buffer=(unsigned char *)calloc(80*25*2, 1);
if(!buffer) exit(1); /* Вы можете здесь сами обработать ошибêó
*/
/* сохранение части эêрана */
gettext(x,y,endx,endy,buffer); // vsave(x,y,endx,endy, buffer);
draw_border(x, y, endx,endy, border, tcolor, foncolor);
/* высвечивание меню на своем месте */
5

display_menu_gor(menu,x+1,y+1,count, menuXpos, border, tcolor, foncolor);
/* ввести выбор пользователя */ choice=user_case_gor(x+1,y+1,count, menuXpos, menu,
keys, tcolor,
foncolor, usercolor);
/* восстановление части эêрана */ puttext(x,y, endx, endy, buffer);
//vrest(x,y,endx,endy, buffer); free(menuXpos);
free(buffer); return choice;
}
void vsave( int l , int t , int r , int b , char far *buf )
{
char far *v , far *tm; register int i;
int lx , ly , j;
lx = b - t + 1; ly = ( r - l + 1 ) * 2; v = VID_MEM + t*160 + l*2;
for( j=0; j<lx; j++ ) { tm = v;
for( i=0 ; i<ly; i++ ) *buf++ = *tm++; v += 160;
};
}
void vrest( int l , int t , int r , int b , const char far *buf )
{
char far *v , far *tm; register int i;
int lx , ly , j;
lx = b - t + 1; ly = ( r - l + 1 ) * 2; v = VID_MEM + t*160 + l*2;
for( j=0; j<lx; j++ ) { tm = v;
for( i=0; i<ly; i++ ) *tm++ = *buf++; v += 160;
};
}
6