На всем протяжении этой книги мы касались, в основном, тех аспектов программирования на Си, которые могут заинтересовать профессиональных программистов, чье основное занятие программирование на Си. Так как возможности программы по взаимодействию с пользователем часто ограничиваются возможностями, представленными в рамках пользовательского интерфейса, то в этой главе содержатся завершенные сведения, так сказать, окончательная точка зрения на возможность и целесообразность манипулирования с экраном дисплея при разработке пользовательского интерфейса. Основное внимание в этой главе уделяется вопросам отображения различных фрагментов текста в разных цветах. Дополнительно в этой главе рассматриваются некоторые другие вопросы программирования пользовательского интерфейса такие, как изменение размера и формы курсора, скроллинг (прокрутка) части текста, сохранение содержимого экрана в виде дискового файла. Использование со вкусом звуковых возможностей компьютера позволяет в значительной мере "оживить" работу пользователя с вашей программой, а также акцентировать внимание пользователя на ряде моментов и ситуаций, возникающих во время работы. В связи с этим в главу включен параграф, поясняющий возможности пользователя по генерации звуков различных частот и созданию различных звуковых эффектов с использованием динамика компьютера.

Подпрограммы, описанные    в    этой                                       главе,                   являются

машинно-зависимыми.  Они могут функционировать на IBM PC, XT, AT,

PS/2 и совместимых с ними моделях. Большинство из подпрограмм требуют наличия в вашей конфигурации компьютера цветного дисплея (адаптера). Если вы имеете несовместимый с вышеперечисленными моделями компьютер, то вам необходимо будет внести в подпрограммы соответствующие изменения.

Использование цвета в текстовом режиме

Ранее вы могли видеть великолепные, профессионально написанные программы, которые не используют цветовые возможности. Как вы уже уяснили из  поддерживает различные видеорежимы. Если вы имеете в своей

системе  цветной  адаптер,  режим  работы  которого  по умолчанию

установлен равным 3,  то это означает, что специфицирован цветной

режим   отображения   текста  80*25  строк.  По  умолчанию  текст

отображается на экране в белом цвете, однако, имеется возможность

отображать текст в других цветах.

Атрибутный байт текстового режима.

Каждый символ отображается на экране дисплея в соответствии с его атрибутным байтом, определяющим как именно отображается символ (см. главу 1). Если компьютер включает в себя цветной адаптер, работающий в видеорежиме, определяемом значением 3, то соответствующее значение атрибутного байта определяет цвет отображаемого символа, цвет фона, интенсивность отображения символа (уровень яркости), а также устанавливает или отменяет режим мерцания символа. Состав атрибутного байта показан в Таблице 8.1.

Биты 0, 1 и 2 атрибутного байта определяют компоненты цвета символа. Например, если установлен бит 0 (значение бита равно 1), то символ отображается в голубом цвете. Если значение всех этих битов не установлено, то символ является неотображаемым. Запомните, что цвета накладываются друг на друга. Если значения всех этих битов установлены (равны 1), символ отображается в белом цвете. Если вы установили значения двух из этих битов, то будет генерирован либо ярко-красный, либо голубой (циановый) цвет символа. Биты с 4 по 6 используются для установки цвета фона. Если значение этих битов не установлено (равно 0), то цвет фона будет черным, в противном случае цвет фона определяется в соответствии со специфицированным значением битов.

На заре микрокомпьютеров режимом, в котором видеосистемой отображались символы по умолчанию, был режим полной яркости, однако наряду с этим режимом имелась возможность отображать символы в режиме пониженной яркости. После реализации IBM PC пользователю был предложен альтернативный путь: По умолчанию отображение символов видеосистемой PC выполняется в режиме "нормальной" яркости, но вы имеете возможность отображать символы в режиме повышенной яркости, устанавливая значение 1 для соответствующего бита атрибутного байта (бита повышенной яркости) В добавок ко всему вы можете установить режим мерцания символа, установив значение соответствующего бита.

Таблица 8-1.

Состав атрибутного байта при работе в 3 видеорежиме

 

Бит

0

1

2

3

4

5

6

7

Устанавливаемое значение

Голубой цвет символа

Зеленый цвет символа

Красный цвет символа

Повышенная яркость символа

Голубой цвет фона

Зеленый цвет фона

Красный цвет фона

Мерцание символа

__

___________

_____________________________________

____________

В предыдущих параграфах были рассмотрены функции, которые выполняли считывание символов на экран, используя при этом как обращение к BIOS, так и непосредственный доступ к видеопамяти. Непосредственный доступ к видеопамяти является необходимым условием повышения скорости реакции задач на действия пользователя. Однако непосредственный доступ к видеопамяти значительно снижает возможность переносимости программ (их мобильность), а также является серьезной помехой при использовании программ в мультизадачных операционных системах типа OS/2. Функции, рассматриваемые в этой главе, используют возможности BIOS и видеопамяти по той причине, что сами по себе эти функции более мобильны и, в конечном итоге, для ускорения их быстродействия обычно не требуется стандартный вывод на дисплей. Следует отметить, что интуитивно использование непосредственного доступа к видеопамяти является более предпочтительным.

Отображение строки в определенном цвете.

Отображение строки в определенном цвете не является столь трудной задачей, как вам может казаться на первый взгляд, если вы используете функции записи символа, которые используют, в свою очередь, возможности BIOS и видеопамяти (ROM-BIOS). ROM-BIOS прерывание 10Н, функция 9 позволяет отобразить текущий символ (один!) в позиции курсора и его атрибуты. Проблема состоит лишь в перемещении курсора по записываемой вами строке, но это должна осуществлять непосредственно ваша подпрограмма.

В соответствии с этим возникает, во-первых, необходимость определения текущей позиции курсора. Для этого используется функция read_cursor_xy(), представленная ниже. Эта функция использует ROM-BIOS-прерывание 10Н, функцию 3, для чтения текущих координат позиции курсора X и Y. Координаты позиции курсора возвращаются в качестве значений аргументов функции.

/* Чтение текущих координат позиции курсора */

void read_cursor_xy(x,y)

char *x,*y;

 

union REGS r;

r.h.ah = 3;  /* чтение текущей позиции курсора */

r.h.bh = 0;  /* видеостраница */

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

*y = r.h.dl;

*x = r.h.dh;

 

После определения координат текущей позиции курсора, функция, которая выполняет печать строки, должна осуществить перемещение курсора к следующему символу, с тем, чтобы используя ROM-BIOS-прерывание напечатать его. Для перемещения курсора целесообразно использовать функцию goto_xy(), которая была уже рассмотрена ранее и приводится в этой главе для полноты изложения материала.

/* Перемещение курсора в позицию, специфицированную

координатами X и Y

*/

void goto_xy (x,y)

int x,y;

 

union REGS r;

r.h.ah = 2; /* функция адресации курсора */

r.h.dl = x; /* координата столбца */

r.h.dh = y; /* координата строки */

r.h.bh = 0; /* видеостраница */

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

 

Функция color_puts(), представленная ниже, отображает специфицированную пользователем строку в указанном цвете.

/* Печать строки в цвете   */

void color_puts(s,color)

char *s;  /* строка */

char color; /* цвет строки */

 

union REGS r;

char x,y;

read_cursor_xy(&x,&y); /* получение текущей позиции курсора

*/

while (*s)

if (*s == ' ')   /* обработка символа новой строки */

printf(" ");

s++;

x = 0; y++;  /* переход на следующую строку */

continue;

 

r.h.ah         =   9; /* функция отображения символа и его атрибутов */

r.h.al          =   *s++;    /* отображаемый символ */

r.h.bl          =   color;   /* атрибуты цвета */

r.h.bh        =   0;       /*видеостраница 0 */

r.x.cx          =   1; /* отобразить за единицу времени ( такт ) */

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

x++;

goto_xy(x,y); /* перемещение курсора */

 

 

Как вы можете видеть, отображаемый символ запоминается в регистре AL, атрибуты цвета символа - в регистре BL, номер видеостраницы - в регистре BH, а количество интервалов времени (тактов процессора), за которое будет отображен символ - в регистре CX. Заметим, что функция также обрабатывает специальный символ новой строки (' '). Вы можете также, по желанию, организовать обработку символов табуляции (' '), двойных кавычек (") и других специальных символов.

Использование функции color_puts() предполагает наличие ряда макроопределений в начале вызывающей функцию программы. Перечень макроопределений представлен ниже

#define BLUE                                          1

#define GREEN                             2

#define RED                                          4

#define INTENSE                         8

#define BLUE_BACK    16

#define GREEN_BACK   32

#define RED_BACK                    64

#define BLINK                             128

Используя эти макросы, вы можете по своему усмотрению выдать

на экран строку текста на фоне установленного вами цвета, а также

саму строку в определенном вами цвете.  Вы можете также управлять

режимом отображения  строки  (повышенная  яркость  или мерцание).

Комбинируя цвета, режимы мерцания или повышенной яркости для одного или совокупности символов, вы можете добиться любого желаемого вами эффекта. Например, представленная ниже строка программы приведет к отображению строки "А это - текст" в режиме повышенной яркости в голубом (циановом) цвете:

color_puts("А это - текст",GREEN | RED | INTENSE );

Использование цвета.

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

- Избегайте использования "нестандартных" цветов. Наиболее общим лучшим вариантом является отображение белых с имволов на черном фоне. Предпочтительнее вместо отображения какой-то важной информации в контрастном цвете отображать ее в режиме повышенной яркости.

- Наиболее эффективным признано использование цветных рамок экрана и окон.

- В ряде ситуаций полезным оказывается отображение отрицательного остатка (например, денежной суммы) в красном цвете.

- Отображение текущей строки (или части текущей строки) в контрастном цвете является, пожалуй, лучшим приемом индикации положения действий пользователя на экране в текущий момент времени.

Изменение размера курсора

Большинство пользователей даже не представляют насколько велики возможности семейства машин IBM PC. В частности, они позволяют изменять размер курсора. По умолчанию курсор отображается в виде одной мерцающей строчки (развертки дисплея). Однако пользователь может варьировать размером курсора от одной строки развертки дисплея до полного размера (высоты) символа. В цветном текстовом режиме курсор может иметь высоту от 0 до 8 строк развертки. (В монохромном режиме курсор может иметь высоту от 0 до 14 строк развертки, однако в данном параграфе мы будем рассматривать только цветной режим). Нижняя строка развертки

имеет номер 0. Лучше всего рассматривать изменение курсора именно

относительно  строки  развертки  0,  так  как  применение другого

метода может привести к значительным расхождениям  результатов на

различных  компьютерах.  (В  принципе  применение  других методов

возможно, однако вам необходимо помнить, что при их использовании

вы можете не добиться соответствия форм курсора при решении одной

и той же задачи на  разных  компьютерах).  При  условии,  что  вы

будете рассматривать изменение формы курсора относительно нулевой

строки  развертки,  изменение  формы  курсора  будет  выполняться

аналогично изображенному на рис.8-1.

Для установления размера курсора вам необходимо использовать ROM-BIOS-прерывание 10Н, функцию 1, которая устанавливает размер курсора. Начало курсора (начальная строка развертки) - запоминается в регистре CН, а конец (конечная строка развертки) в регистре CL.

Строка развертки

7 ----- | |

6 ----- | | | | | |

5 ----- | | | | | | | | | |

4 ----- | | | | | | | | | | | | | |

3 ----- | | | | | | | | | | | | | | | | | |

2 ----- | | | | | | | | | | | | | | | | | | | | | |

1 ----- | | | | | | | | | | | | | | | | | | | | | | | | | |

0 | | | | | | | | | | | | | | ----- ----- ----- ----- ----- ----- -----

Рис. 8-1.  Возможность изменения формы курсора в цветном режиме.

Функция size_cursor(), представленная ниже, устанавливает размер курсора.

/* Установление размера курсора */

void size_cursor(start,end)

char start,end; /* начальная и конечная строки развертки */

 

union REGS r;

r.h.ah = 1; /* функция адресации курсора */

r.h.ch = start;

r.h.cl = end;

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

 

При использовании функции size_cursor() укажите желаемые начальную и конечную строки развертки, определяющие размер курсора. Например, следующая конструкция позволяет установить высоту курсора в три строки развертки:

size_cursor(0,2);

Форма курсора может быть изменена либо очередным вызовом функции size_cursor(), либо изменением видеорежима.

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

Скроллинг части экрана

Две совместно используемые функции ROM-BIOS-прерывания позволяют осуществлять скроллинг вперед и назад части экрана. Эти функции были включены в ROM-BIOS для поддержки многооконных интерфейсов. Как вы знаете, когда курсор расположен в двадцать пятой строке и вы нажали клавишу <ВВОД>, то автоматически осуществляется перемещение текста на одну строку вверх с целью отображения новой строки в нижней части экрана. Точно так же, с помощью функций 6 и 7 прерывания ROM-BIOS 10Н, можно осуществить скроллинг лишь части экрана. Функция 6 позволяет выполнить скроллинг в окне вниз (вперед), а функция 7 - вверх (назад).

Обе функции при вызове используют информацию, хранимую в определенных регистрах. Занесите количество строк, на которые будет "прокручиваться" текст (мощность скроллинга) в регистр AL. Номер верхней левой строки, ограничивающей ваше "окно", занесите в регистр CH, а номер верхнего левого столбца - в регистр CL. Номер нижней левой строки занесите в регистр DH, а номер нижнего правого столбца - в регистр DL. В конце запомните в регистре BH атрибуты режима отображения, которые будут определять, как именно будут отображаться в процессе скроллинга новые строки. Функция scroll_window() представлена ниже.

/* Скроллинг в окне вперед и назад */

void     scroll_window(startx,starty,endx,endy,lines,direct)

char      startx,starty;/* верхний левый угол */

char      endx,endy;    /* нижний правый угол */

char      lines;        /* число строк прокрутки */

char      direct;       /* вперед или назад */

 

union REGS r;

if ( direct == UP ) r.h.ah = 6; /* скроллинг вперед */

else r.h.ah = 7; /* скроллинг вниз (назад) */

r.h.al          =   lines;

r.h.ch         =   starty;

r.h.cl          =   startx;

r.h.dh        =   endy;

r.h.dl          =   endx;

r.h.bh        =   0;     /* режим отображения */

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

 

Вы можете определить макрос UP как имеющий некоторое значение. Вы также можете определить макрос DOWN, значение которого будет отлично от UP, а затем использовать при необходимости осуществления скроллинга в окне эти макроопределения. Такой прием значительно упростит вашу программу. Функция scroll_window() присваивает регистру ВН значение 0 для сохранения пустых строк, однако вы можете изменить это значение по своему усмотрению.

Простейшая демонстрационная программа

Эта программа позволяет продемонстрировать работу функций, рассмотренных в данной главе до настоящего момента. Эти функции позволяют изменить форму курсора, выдать сообщение в цвете, а также использовать скроллинг части экрана. Результат работы этой программы представлен на рис.8-2.

-----------------------------------------------------------------

|                                                                                                                                                                          |

|   a)     Это - тест                                                                                                                                             |

|     aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa                                                         |

|     bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb                                       |

|     cccccccccccccccccccccccccccccccccccccccccccccccccccccc                                                         |

|     dddddddddddddddddddddddddddddddddddddddddddddddddddddd                                       |

|     eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee                                                         |

|     ffffffffffffffffffffffffffffffffffffffffffffffffffffff                                                                                             |

|     gggggggggggggggggggggggggggggggggggggggggggggggggggggg                                       |

|     hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh                                       |

|     iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii                                                                                                               |

|     jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj                                                                                                               |

|     kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk                                                         |

|     llllllllllllllllllllllllllllllllllllllllllllllllllllll                                                                                                               |

|     mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm   |

|     nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn                                       |

|     oooooooooooooooooooooooooooooooooooooooooooooooooooooo                                       |

|     pppppppppppppppppppppppppppppppppppppppppppppppppppppp                                       |

|     qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq                                       |

|     rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr                                                                                             |

|     ssssssssssssssssssssssssssssssssssssssssssssssssssssss                                                         |

|     tttttttttttttttttttttttttttttttttttttttttttttttttttttt                                                                                             |

|     uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu                                       |

|     vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv                                       |

|                                                                                                                                                                          |

|     б) Это - тест.                                                                                                                                              |

|     aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa                                                         |

|     bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb                                       |

|     cccccccccccccccccccccccccccccccccccccccccccccccccccccc                                                         |

|     dddddddddddddddddddddddddddddddddddddddddddddddddddddd                                       |

|     eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee                                                         |

|     ffffffffffffffffffffffffffffffffffffffffffffffffffffff                                                                                             |

|     gggggggggggggggggggggggggggggggggggggggggggggggggggggg                                       |

|     hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh                                       |

|     iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii                                                                                                               |

|     jjjjjjjjjj                     jjjjjjjjjjjjjjjjjjjjjjj                                                                                                               |

|     kkkkkkkkkk                     kkkkkkkkkkkkkkkkkkkkkkk                                                                              |

|     llllllllll                     lllllllllllllllllllllll                                                                                                               |

|     mmmmmmmmmmjjjjjjjjjjjjjjjjjjjjjmmmmmmmmmmmmmmmmmmmmmmm                                             |

|     nnnnnnnnnnkkkkkkkkkkkkkkkkkkkkknnnnnnnnnnnnnnnnnnnnnnn                                              |

|     oooooooooolllllllllllllllllllllooooooooooooooooooooooo                                                                   |

|     pppppppppppppppppppppppppppppppppppppppppppppppppppppp                                       |

|     qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq                                       |

|               rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr    |

|               ssssssssssssssssssssssssssssssssssssssssssssssssssssss    |

|               tttttttttttttttttttttttttttttttttttttttttttttttttttttt    |

|               uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu    |

|               vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv    |

|                                                                                                                                                                          |

-----------------------------------------------------------------

Рис. 8-2 Результат работы программы.

/* Демонстрационная программа печати текста в цвете,

изменения формы курсора и скроллинга в окне

*/

#include "dos.h"

#define BLUE                               1

#define GREEN                             2

#define RED                                  4

#define INTENSE                         8

#define BLUE_BACK   16

#define GREEN_BACK  32

#define RED_BACK    64

#define BLINK                        128

#define UP                            0

#define DOWN                            1

void mode(),color_puts(),palette(), read_cursor_xy();

void goto_xy(),size_cursor(),scroll_window();

main()

 

int i,j;

mode(3); /* режим текстовый, цветной */

size_cursor(0,3);

goto_xy(0,0);

color_puts(" Это - тест ",BLUE |RED | INTENSE);

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

for ( j=0;j<79;j++)

printf("%c",i+'a');

printf(" ");

 

getche();

scroll_window(10,10,50,15,3,DOWN);

getche();

 

/* Печать строки в цвете */

void color_puts(s,color)

char *s;                       /* строка */

char color;   /* цвет строки */

 

union REGS r;

char x,y;

read_cursor_xy(&x,&y); /* чтение текущей позиции

курсора   */

while (*s)

if (*s == ' ')  /* обработка символа новой

строки */

printf(" ");

s++;

x = 0; y++;  /* переход к новой строке */

continue;

 

r.h.ah         =   9;/* отображение символов по атрибутам */

r.h.al          =   *s++; /* выдаваемый символ */

r.h.bl          =   color;  /* атрибут цвета */

r.h.bh        =   0; /*     видеостраница 0 */

r.x.cx          =   1; /* выдача символа за один такт */

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

x++;

goto_xy(x,y);                           /* перемещение курсора */

 

 

/* чтение текущей позиции курсора */

void read_cursor_xy(x,y)

char *x,*y;

 

union REGS r;

r.h.ah = 3; /* чтение позиции курсора */

r.h.bh = 0; /* видеостраница 0 */

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

*y = r.h.dl;

*x = r.h.dh;

 

/* установка палитры */

void palette(pnum)

int pnum;

 

union REGS r;

r.h.bh = 1;  /* код для графического режима 4 */

r.h.bl = pnum;

r.h.ah = 11; /* функция установки палитры */

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

 

/* установка видеорежима */

void mode(mode_code)

int mode_code;

 

union REGS r;

r.h.al = mode_code;

r.h.ah = 0;

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

 

/* перемещение курсора в позицию x,y */

void goto_xy(x,y)

int x,y;

 

union REGS r;

r.h.ah = 2; /* функция адресации курсора */

r.h.dl = x; /* координаты столбца */

r.h.dh = y; /* координаты строки */

r.h.bh = 0; /* видеостраница 0 */

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

 

/* установка размера (формы) курсора */

void size_cursor(start,end)

char start,end; /* начальная и конечная строки

развертки */

 

union REGS r;

r.h.ah = 1; /* функция адресации курсора */

r.h.ch = start;

r.h.cl = end;

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

 

/* скроллинг в окне вперед и назад */

void     scroll_window(startx,starty,endx,endy,lines,direct)

char      startx,starty; /* верхний левый угол */

char      endx,endy;     /* нижний правый угол */

char      lines;         /* мощность скроллинга */

char      direct;        /* вверх или вниз */

 

union REGS r;

if ( direct == UP ) r.h.ah = 6; /* скроллинг вверх */

else r.h.ah = 7; /* скроллинг вниз */

r.h.al          =   lines;

r.h.ch         =   starty;

r.h.cl          =   startx;

r.h.dh        =   endy;

r.h.dl          =   endx;

r.h.bh        =   0; /* режим отображения */

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

 

Сохранение копии экрана в дисковом файле.

Ни в DOS, ни в OS/2 нет утилит, сходных с утилитой печати копии экрана, позволяющей сохранять текущее содержимое экрана дисплея в дисковом файле. В этом разделе вы найдете пояснение, как можно создать программу, которая выполняла бы именно эту функцию.

Эта программа использует ROM-BIOS-прерывание 10Н, функцию 8 для чтения символа из текущей позиции курсора, после чего этот символ записывается в файл на диске. Как и в предыдущем разделе, вы опять встретитесь с функцией goto_xy(), которая в этом случае используется для перемещения курсора последовательно по всем строкам экрана, начиная с левого верхнего угла экрана до правого нижнего угла.

Имя файла, в котором будет храниться копия экрана, указываетя в качестве аргумента программы. Если, к примеру, вы назовете свою программу, копирующую экран на диск, screen, то представленная ниже командная строка приведет к созданию копии экрана в файле с именем scr.sav:

C> screen scr.sav

А вот исходный текст самой программы копирования:

/* Эта программа копирует содержимое экрана вашего

дисплея в файл, имя которого указано в командной

строке

*/

#include "dos.h"

#include "stdio.h"

void save_screen(),goto_xy();

main(argc,argv)

int argc;

char *argv[];

 

if ( argc != 2 )

printf(" используйте формат : screen <имя файла>");

exit(1);

 

save_screen(argv[1]);

 

/* сохранение содержимого экрана в дисковом файле */

void save_screen(fname)

char *fname;

 

FILE *fp; union REGS r;

register char x,y;

if ( !( fp=fopen(fname,"w")))

printf(" Файл не может быть открыт ");

exit(1);

 

for (y=0;y<25;y++)

for (x=0;x<80;x++)

goto_xy(x,y);

r.h.ah = 8; /* чтение символа */

r.h.bh = 0; /* видеостраница */

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

putc(r.h.al,fp); /* выдача (печать) символа */

 

fclose(fp);

 

/* Перемещение курсора в позицию (x,y) */

void goto_xy(x,y)

int x,y;

 

union REGS r;

r.h.ah = 2; /* функция адресации курсора */

r.h.dl = x; /* координата столбца */

r.h.dh = y; /* координата строки */

r.h.bh = 0; /* видеостраница */

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

 

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

А теперь добавим звук.

Использование со вкусом звука значительно повышает привлекательность программ. Звук может быть использован в широком спектре от тоненького "писка" машины до исполнения музыки или различных специальных эффектов. В этом параграфе вы научитесь, как можно управлять высотой и продолжительностью звучания нот, генерируемых динамиком компьютера. Мы также продемонстрируем вам некоторые наиболее интересные звуковые эффекты.

Программируемый таймер 8253.

Генерация звуков в компьютере PC выполняется с помощью программируемого таймера 8253, который применяется для управления колебаниями динамика. Управление колебаниями динамика определяется частотой, которая, в свою очередь, определяется содержимым различных внутренних регистров. Значения этих регистров устанавливаются при записи в определенные порты. Порт 66 используется для спецификации счетчика, который использует таймер при определении интервала колебаний динамика. Таймер работает в строгом соответствии с частотой системного таймера и специфицированным значением счетчика, определяющим колебания динамика. Затем, после обнуления счетчика происходит установка нового значения счетчика, и весь цикл функционирования программируемого таймера повторяется сначала. Значение счетчика определяется по следующей формуле:

count = 1,193,180/требуемая частота

где 1,193,180 есть тактовая частота системного таймера.

Регистр-счетчик таймера 8253 устанавливается в следующей последовательности (значение счетчика задается двухбайтным числом):

1. Выдать в порт 67 значение 182 (означающее, что будет устанавливаться счетчик).

2.  Выдать в порт 66 младший байт числа, определяющего значение счетчика.

3.  Выдать в порт 66 старший байт числа, определяющего значение счетчика.

Динамики большинства компьютеров класса PC не позволяют воспроизводить полный спектр частот, воспринимаемых человеческим слухом (от 20 Гц до 18.000 Гц). Однако динамик позволяет воспроизводить ноты лучше, чем динамики других компьютеров в пределах 12000 Гц и даже выше. В основном же динамик используется в пределах 100-5000 Гц.

Итак, таймер установлен. Однако динамик еще не будет воспроизводить звук, так как не включен. Таймер 8253 активен постоянно, а динамик требует дополнительной команды включения. Активизация динамика осуществляется путем установки значений битов 0 и 1 регистра программируемого периферийного интерфейса, задание значений которого выполняется через порт 97. Если значения этих двух битов установлены (равны 1), то динамик издает звук частотой, установленной счетчиком 8253. Если значения этих битов равны 0, то никакой звук генерироваться не будет. Остальные биты этого байта используются другими устройствами, поэтому интерпретация значения левых битов не может быть изменена. Таким образом, для установки значений управляющих динамиком бит

необходимо выполнить следующую последовательность действий:

1. Получить текущее значение регистра из порта 97.

2. Сравнить это значение с 3 или установить равным 3.

3. Записать результат в порт 97.

Для того, чтобы выключить динамик, необходимо переслать в порт значение 253.

Простейшим приемом, позволяющим читать и писать байт из или в порт, в Си является использование соответствующих функций. В Турбо Cи - это функции inportb() и outportb(). В Microsoft Cи - это функции inp() и outp(). Они имеют следующий общий формат:

int inportb(int port);

void outportb(int port, char value);

int inp(unsigned port);

int outp(unsigned port, int value);

В других компиляторах Си эти функции могут иметь иные названия, но обязательно будут присутствовать в вашей библиотеке, так как являются одними из базовых функций версий Си для ПЭВМ. В программах, приведенных в этом параграфе, используются функции Турбо Cи.

Простейший способ проверки слуха.

Вы обладаете возможностью сделать несколько грубый, но эффективный тест слуха, который в состоянии обнаружить некоторые типы дефекта слуха. Как вы ранее узнали, динамик большинства компьютеров серии PC не воспроизводит звуки выше 12000 Гц. Однако ряд людей, у которых отмечены некоторые отклонения слуха, не могут услышать звук даже такой частоты. Фактически, тестируя свой слух, вы будете несколько удивлены тем, насколько высоким окажется звук с частотой 12000 Гц. (Предупреждение: тестирование слуха с помощью этого теста можно производить лишь ради шутки. Он, естественно, не позволяет действительно оценить слух испытуемого. Поэтому, если вы заметили у себя дефекты слуха или хотите действительно проверить свой слух, обратитесь лучше к своему врачу).

Для получения звука в тесте используется функция sound(), которая генерирует непродолжительное звучание специфицированной ноты. Как показано ниже, эта функция содержит все необходимое для того, чтобы сгенерировать любой звук с помощью динамика компьютера.

/* Звучание динамика на заданной частоте */

void sound(freq)

int freq;

 

unsigned i;

union

long divisor;

unsigned char c[2];

 count;

unsigned char p;

count.divisor = 1193280 / freq; /* вычисление небходимого

значения счетчика */ outportb(67,182); /* обращение к таймеру 8253 после

установки счетчика */ outportb(66,count.c[0]); /* пересылка младшего байта */ outportb(66,count.c[1]); /* пересылка старшего байта */ p = inportb(97); /* чтение существующего шаблона бит */ outportb(97,p|3); /* установка битов 0 и 1 */

for (i=0;i<64000;++i); /* цикл задержки */

outportb(97,p); /* восстановление первоначального значения

шаблона бит для отключения динамика */

 

Заметим, что  частота  звучания  ноты  специфицирована   как

аргумент функции. Цикл задержки необходим, так как без него вы бы

услышали  только  мгновенный  "щелчок"  или  "писк".  Вы   можете

изменить  частоту  работы  системного  таймера  процессора вашего

компьютера.  При этом,  оформив  его  как  параметр  функции,  вы

добьетесь  определенной  эффективности  вашей программы.  Функция

sound()  может  использоваться   и   для   получения   банального

"пищания" компьютера.

Управляющая функция для программы теста слуха представлена ниже.

/* Простейший тест слуха */

#include "dos.h"

void sound();

main()

 

int freq;

do

printf(" Введите частоту ( 0 - выход ): ");

scanf("%d",&freq);

if ( freq ) sound(freq);

 while(freq);

 

При использовании теста, в возрастающем порядке указывайте частоту звука до тех пор, пока звук воспринимается на слух. Для выхода введите 0.

Имитация звука сирены и взврыва.

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

Например, для создания эффекта звучания сирены вы должны варьировать частоту звука между двумя конечными точками. Высота звука должна изменяться от меньшей к большей, а затем уменьшаться от большей к меньшей. Функция siren(), представленная ниже, использует этот метод для создания эффекта звучания сирены.

#define DELAY 10000

/* Создание эффекта звучания сирены */

void siren()

 

unsigned i,freq;

union

long divisor;

unsigned char c[2];

 count;

unsigned char p;

p = inportb(97); /* чтение существующего шаблона бит */

outportb(97,p|3); /* установка бит 0 и 1 */

/* повышение звука сирены */

for (freq = 1000;freq<3000;freq+=RATE)

count.divisor = 1193280 / freq; /* вычисление нужного

значения счетчика */ outportb(67,182); /* обращение к таймеру 8253 после

определения значения счетчика */ outportb(66,count.c[0]); /* пересылка младшего байта */ outportb(66,count.c[1]); /* пересылка старшего байта */

for (i=0;i

 

/* понижение звука сирены */

for (;freq>1000;freq-=RATE)

count.divisor = 1193280 / freq; /* вычисление нужного

значения счетчика */ outportb(67,182); /* обращение к таймеру 8253 после

определения значения счетчика */ outportb(66,count.c[0]); /* пересылка младшего байта */ outportb(66,count.c[1]); /* пересылка старшего байта */

for (i=0;i

 

outportb(97,p); /* восстановление начального вида шаблона

бит для отключения динамика */

 

Вы можете переопределить значение макроса DELAY в зависимости от производительности вашего компьютера и вашего вкуса. Как вы видите, функция siren() выполняет один полный цикл звучания сирены и на этом завершает свою работу. Для получения эффекта продолжительного звучания сирены вам надо поместить обращение к siren() в цикл.

Для имитации звука взрыва, который используется во многих видеоиграх, можно модифицировать функцию siren() таким образом, чтобы она позволяла генерировать звук лишь нисходящей частоты. Функция laser(), представленная ниже, позволяет получить этот эффект.

#define DELAY 10000

/* получение эффекта взрыва */

void laser()

 

unsigned i,freq;

union

long divisor;

unsigned char c[2];

 count;

unsigned char p;

p = inportb(97); /* чтение существующего шаблона бит */

outportb(97,p|3); /* установка бит 0 и 1 */

/* взрыв */

for (;freq>1000;freq-=RATE)

count.divisor = 1193280 / freq; /* вычисление нужного

значения счетчика */

outportb(67,182); /* обращение к таймеру 8253 после

определения значения счетчика */ outportb(66,count.c[0]); /* пересылка младшего байта */ outportb(66,count.c[1]); /* пересылка старшего байта */

for (i = 0;i

 

outportb(97,p); /* восстановление начального вида шаблона

бит для отключения динамика */

 

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

Создание "космической музыки".

Соединив воедино произвольное количество стандартных функций Си rend() и sound(), вы создадите "космическую" музыку. Звук, получаемый при выполнении программы, представленной ниже, напоминает "музыку звезд" в старых научно-фантастических фильмах. Несмотря на то, что все звуки генерируются произвольным образом, ритм и рисунок мелодии, возникающие время от времени, действительно оставляют впечатление "небесной музыки".

/* Космическая музыка звезд */

#define DELAY 64000

#include "dos.h"

void sound();

main()

 

int freq;

do

do

freq = rand();

 while (freq>5000); /* после персонального

прослушивания */ sound(freq);

 while (!kbhit());

 

/* звучание динамика на специфицированной частоте */

void sound(freq)

int freq;

 

unsigned i;

union

long divisor;

unsigned char c[2];

 count;

unsigned char p;

count.divisor = 1193280 / freq; /* вычисление нужного

значения счетчика */ outportb(67,182); /* обращение к таймеру 8253 после

определения значения счетчика */ outportb(66,count.c[0]); /* пересылка младшего байта */ outportb(66,count.c[1]); /* пересылка старшего байта */

p = inportb(97); /* чтение существующего шаблона бит */

outportb(97,p|3); /* установка бит 0 и 1 */

for (i = 0;i

компьютеров

32000 для 6 МГц PC/AT

20000 для стандарта PC и XT */

outportb(97,p); /* восстановление начального вида

шаблона бит для отключения динамика */

 

Эта программа генерирует звуки частотой менее 5000 Гц, так как звуки именно в пределах этой частоты наиболее мягко воспринимаются слухом и не выходят за границы, воспринимаемые ухом человека.

Рекомендуем вам поэкспериментировать с этой программой, установив произвольную длину интервала времени между звуками или фильтруя значения, передаваемые в sound(). Возможны и другие варианты развития вашего творчества.