Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
МП 1,2.doc
Скачиваний:
11
Добавлен:
05.11.2018
Размер:
2.77 Mб
Скачать

6. Лабораторная 1

Задание

Написать программу, имитирующую работу пользователя в режиме редактирования. При нажатии обычных клавиш на экран выводятся соответствующие им буквы.

Если нажата одна из клавиш: «стрелка влево», «стрелка вверх», «стрелка вправо», «стрелка вниз», то курсор продвигается на одну позицию в указанном направлении. Исчезающее меню вызывается с помощью клавиши <F2>.

В зависимости от варианта исчезающее меню выводится горизонтально, либо вертикально, и состоит из четырех опций, одного из видов:

3.

Цвет вывода

Фон

Эхо

Выход


2.

Курсор

Палитра

Эхо

Выход


1.

Сохранение

Восстановление

Эхо

Выход


Горячие клавиши для первого вида меню: ‘1’, ‘2’, ‘3’, ‘4’; для второго: ‘К’, ‘П’, ‘Э’, ‘В’; для третьего: ‘Ц’, ‘Ф’, ‘Э’, ‘В’.

После выбора опции меню исчезает, и производится одно из действий:

  • эхо – возврат в режим редактирования;

  • выход – конец работы программы;

  • сохранение – сохранение содержимого экрана в файл R.TXT;

  • восстановление – чтение файла R.TXT и вывод его на экран;

  • курсор – изменение размеров курсора;

  • палитра – смена палитры;

  • цвет вывода – изменение цвета символов, которые выводятся на экране при нажатии клавиш;

  • фон – изменение цвета фона символов.

Опишем распределение по вариантам положения и опции меню. Видам меню присвоим номера 1, 2 и 3. Горизонтальное меню обозначим буквой ‘Г’, вертикальное – буквой ‘В’. Положения меню: “слева и сверху”, “слева и внизу”, “справа и сверху”, “в центре” означают, где расположена линейка или столбик меню. Например, в левом верхнем углу или в центре экрана.

Варианты заданий

Слева и сверху

1

2

3

4

5

6

Слева и внизу

7

8

9

10

11

12

Справа и внизу

13

14

15

16

17

18

Справа и сверху

19

20

21

22

23

24

В центре

25

26

27

28

29

30

В клетках расположены номера вариантов. Например, в варианте 15 студент создает меню 2 (“Курсор”, “Палитра”, “Эхо”, “Выход”), выводящееся горизонтально (‘Г’) и находящееся в правой нижней области экрана.

Пример выполнения задания

Требуется написать программу, работающую в режиме “Эхо”. Подпрограмма исчезающего меню включает опции “Курсор”, “Палитра”, “Эхо”, “Выход” и поддерживает горячие клавиши кпэв. Меню представляет собой горизонтальную линейку и выводится слева, в средней линии экрана.

Решение. Для изменения курсора воспользуемся подпрограммой setcursortype() из пп. 1.5. Линию и нижнюю строки курсора будем устанавливать случайно. Для изменения всех регистров палитры применим подпрограмму randpalette() из пп. 1.5. Для установки позиции меню выберем x = 0, y = 10. Максимальную длину строк меню можно передавать в подпрограммы как параметр. Чтобы не было больших отличий от вывода меню вертикально, будем вычислять эту длину в каждой из подпрограмм popup(), display_menu(), get_resp(). Преобразуя эти подпрограммы, получаем следующий текст программы:

#include "stdio.h"

#include "dos.h"

#include "stdlib.h"

#include "time.h"

#include "string.h"

#include "bios.h"

#include "ctype.h"

#include "conio.h"

#define BORDER 1

#define ESC 27 // Escape

#define ENTER 13

#define BKC 8

#define F1 59 // F1

#define F2 60 // F2

#define REV_VID 0x70

#define NORM_VID 7

#define LEFT 75 // стрелка влево

#define RIGHT 77 // стрелка вправо

#define UP 72 // стрелка вверх

#define DOWN 80 // стрелка вниз

void save_video(int, int, int, int, unsigned char*);

void restore_video(int, int, int, int, unsigned char *);

void display_menu(char**,int,int,int,int,int);

void draw_border(int, int, int, int);

void write_string(int, int, char*, int);

void write_char(int,int,char,int);

void select(char**, int);

int popup(char**,char*,int,int,int,int);

int get_resp(int,int,int,char**,char*);

int is_in(char*, char);

int video_mode();

void respalette() ;

void randpalette();

void randcursortype();

char far *vid_mem;

int last_x, last_y;

int TEXT_ATTR=14, TEXT_COLOR=0, BK_COLOR=0;

char *menu[] =

{

" Курсор ",

" Палитра ",

" Эхо ",

" Выход "

};

void main(void)

{

char press;

int x,y;

clrscr(); //очистка экрана

int vmode = video_mode();

if((vmode!=2) && (vmode!=3) && (vmode!=7))

{

printf(" должен быть 80 символьный текстовый режим");

exit(1);

}

/* присвоить соответствующий адрес видеопамяти */

if(vmode==7)

vid_mem=(char far *)0xB0000000; //монохромный режим

else

vid_mem=(char far *)0xB8000000; //цветной режим

window(2,2,79,24);

gotoxy(1,1);

while(1)

{

press = getch();

if(!press) press = getch(); //расширенная клавиатура

x=wherex(), y=wherey();

switch(press)

{

case LEFT : gotoxy(x-1,y);break;

case RIGHT: gotoxy(x+1,y);break;

case UP : gotoxy(x,y-1);break;

case DOWN : gotoxy(x,y+1);break;

case F1 : write_string(1,24,"F2 - меню, ESC - выход",TEXT_ATTR);

break;

case F2 : last_x=x;last_y=y;

popup(menu,"кпэв",4,0,10,BORDER); break;

case ENTER: cprintf("\n\r"); break;

case BKC : if (x==1) gotoxy(78,y-1);

else gotoxy(x-1, y);

write_char(wherex(),wherey(),' ',TEXT_ATTR); break;

case ESC : respalette();exit(1); break;

default : write_char(x,y, press,TEXT_ATTR);

if(x==78) gotoxy(1,y+1);

else gotoxy(x+1,y); break;

}

}

}

/* вывести исчезающее меню и вернуть выбор

возвращает -2, если меню не может быть создано

возвращает -1, если пользователь нажал клавишу ESC

в остальных случаях она возвращает номер выбранного

режима, начиная с 0 */

int popup( char *menu[], /* текст меню */

char *keys, /* горячие клавиши */

int count, /* число режимов */

int x, int y, /* координаты левого верхнего угла */

int border) /* если 0, то без рамки */

{

register int i,len;

int endx, endy, choice;

unsigned char *p;

if((x>79)||(x<0)||(y>24)||(y<0))

{

printf(" выход за пределы экрана");

return -2;

}

/* вычисление размеров меню*/

len=0;

for(i=0;i<count;i++)

if(strlen(menu[i]) > len)

len = strlen(menu[i]);

endx=len*count+x+1;

endy=y+2;

if((endx>79) || (endy>24))

{

printf(" выход за пределы экрана");

return -2;

}

/* размещение памяти для видеобуфера */

p=(unsigned char *)malloc((len*count+2)*3*2);

if(!p) exit(1); /* Вы можете здесь сами обработать ошибку */

/* сохранение части экрана */

save_video(x, endx, y, endy, p);

/* рисуем рамку, если необходимо */

if(border) draw_border(x,y,endx,endy);

/* высвечивание меню на своем месте */

display_menu(menu,x+1,y+1,endx-1, endy-1, count);

/* ввести выбор пользователя */

choice=get_resp(x+1,y+1,count,menu,keys);

select(menu, choice);

/* восстановление части экрана */

restore_video(x, endx, y, endy, p);

/* освобождаем память */

free(p);

return choice;

}

/* высвечивание меню на своем месте */

void display_menu( char* menu[],

int startx,

int starty,

int endx,

int endy,

int count)

{

register int i, j;

int len;

//Закраска области меню

for(i=starty; i<=endy;i++)

for(j=startx; j<=endx; j++)

write_char(j, i , ' ', NORM_VID);

len=0;

for(i=0;i<count;i++)

if(strlen(menu[i]) > len)

len = strlen(menu[i]);

for(i=0;i<count;i++,startx+=len)

write_string(startx, starty, menu[i], NORM_VID);

}

/* рисование рамки меню*/

void draw_border(int startx, int starty, int endx, int endy)

{

register int i;

write_char(startx, starty, 218, NORM_VID);

write_char(endx, starty, 191, NORM_VID);

write_char(startx, endy, 192, NORM_VID);

write_char(endx, endy, 217, NORM_VID);

for(i=startx+1; i<endx; i++)

{

write_char(i, starty, 196, NORM_VID);

write_char(i, endy, 196, NORM_VID);

}

for(i=starty+1;i<endy;i++)

{

write_char(startx, i,179, NORM_VID);

write_char(endx, i,179, NORM_VID);

}

}

/* ввести выбор пользователя */

int get_resp(int x, int y, int count, char* menu[], char* keys)

{

union inkey

{

char ch[2];

int i;

} c;

int arrow_choice=0, key_choice;

int i, len=0;

for(i=0;i<count;i++)

if(strlen(menu[i]) > len)

len = strlen(menu[i]);

/* осветить первый выбор */

write_string(x, y, menu[0], REV_VID);

for(;;)

{

while(!bioskey(1)); // ждать нажатия

c.i=bioskey(0);

/* вернуть выбор в нормальный режим */

write_string(x+len*arrow_choice, y, menu[arrow_choice], NORM_VID);

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 ' ' : arrow_choice++; break;

case ESC : return -1; // выйти

}

}

else // специальная клавиша

{

switch(c.ch[1])

{

case LEFT : arrow_choice--; // стрелка вниз

break;

case RIGHT: arrow_choice++; // стрелка вверх

break;

}

}

/* осуществить цикличность меню */

if(arrow_choice==count) arrow_choice=0;

if(arrow_choice<0) arrow_choice=count-1;

/* подсветить выбранную опцию */

write_string(x+arrow_choice*len, y, menu[arrow_choice], REV_VID);

}

}

/* вывод строки с определенным атрибутом */

void write_string(int x, int y, char* p, int attrib)

{

register int i;

char far *v; //адрес символа

v = vid_mem; //в v помещаем адрес начала видеопамяти

v += y*160+x*2; //вычисляем адрес начала строки в видеопамяти

for(i=y;*p;i++)

{

*v++ = *p++; //записываем в видеопамять символ

*v++ = attrib; //записываем в видеопамять атрибут

}

}

/* запись символа с определенным аттрибутом */

void write_char(int x, int y, char ch, int attrib)

{

char far *v; //адрес символа

v = vid_mem; //в v помещаем адрес начала видеопамяти

v += y*160+x*2; //вычисляем адрес символа в видеопамяти

*v++ = ch; //записываем в видеопамять символ

*v = attrib; //записываем в видеопамять атрибут

}

/* сохранение части экрана с использованием

прямого доступа к видеопамяти */

void save_video( int startx,

int endx,

int starty,

int endy,

unsigned char *buf_ptr)

{

register int i, j;

char far *v, far *t;

v=vid_mem;

for(i=starty;i<=endy;i++)

{

for(j=startx; j<=endx; j++)

{

t = v+i*160+j*2; // вычисляем адрес

*buf_ptr++ = *t++; // записываем в буфер символ

*buf_ptr++ = *t; // записываем в буфер атрибут

}

}

}

/* восстановление части экрана с использованием

прямого доступа к видеопамяти */

void restore_video( int startx,

int endx,

int starty,

int endy,

unsigned char *buf_ptr)

{

register int i,j;

char far *v,far *t; // временные переменные

v=vid_mem; // адрес начала видеопамяти

t=v;

for(i=starty; i<=endy; i++)

{

for(j=startx; j<=endx; j++)

{

v = t;

v += i*160+j*2; // вычисление адреса

*v++ = *buf_ptr++; // восстановление из буфера символа

*v = *buf_ptr++; // восстановление из буфера атрибута

}

}

}

/* запрос текущего видеорежима */

int video_mode()

{

union REGS r;

r.h.ah = 15; /* получить режим */

return int86(0x10,&r,&r) & 255;

}

/* проверка принадлежности символа с строке s */

int is_in(char* s, char c)

{

register int i;

for(i=0; *s; i++)

if(*s++ == c) return i+1;

return 0;

}

/* анализ выбора пункта меню */

void select(char* menu[], int pos)

{

// здесь должна быть Ваша обработка событий меню

switch(pos)

{

case 0: randcursortype();

break;

case 1: randpalette();

break;

case 2: return;

case 3: respalette(); exit(1);

}

}

void respalette()

{

union REGS r;

r.h.ah = 0;

r.h.al = video_mode();

int86(0x10,&r,&r);

}

void setcursortype(int h, int l)

{

union REGS r;

r.x.ax = 0x0100;

r.x.bx = 0;

r.h.ch = h; r.h.cl = l;

int86(0x10,&r,&r);

}

void randcursortype()

{

setcursortype(random(20),random(20));

}

void setpalette(char i, char red, char green, char blue)

{

union REGS r;

r.h.ah = 0x10;

r.h.al = 0;

r.h.bl = i;

r.h.bh = (red%2)*32 + (red/2)*4 +

(green%2)*16 + (green/2)*2 +

(blue%2)*8 + (blue/2);

int86(0x10,&r,&r);

}

void randpalette()

{

int i;

for (i=0; i<16; i++)

setpalette(i, random(3), random(4),random(4));

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]