Глава знакомит читателей с основными функциями стандартной библиотеки трансляторов Microsoft Quick C 2.5 и C 6.0, предназначенными для управления экраном дисплея в текстовом режиме. Глава содержит описание функций, управляющих формой и координатами курсора, текущим режимом работы видеоадаптера и переключением страниц видеопамяти, отображением текста и изменением цвета символов и цвета фона.
Функция позволяет в текстовых режимах видеоадаптеров погасить курсор. Приведем ее прототип:
short _displaycursor( short toggle );
Параметр toggle равен _GCURSOROFF, если курсор необходимо погасить и _GCURSORON, если его надо высветить.
Функция возвращает предыдушее значение toggle, тоесть определяет отображался ли курсор на экране до вызова функции. Описание функции находится в файле graph.h.
Пример использования функции:
#include <stdio.h> #include <graph.h> void main(void) { // очищаем экран дисплея _clearscreen( _GCLEARSCREEN ); // гасим курсор _displaycursor( _GCURSOROFF ); printf("\nКурсор погашен"); getch(); // восстанавливаем курсор _displaycursor( _GCURSORON ); printf("\nКурсор включен"); getch(); }
Функция позволяет определить форму курсора, тоесть положение его верхней и нижней границы:
short _gettextcursor( void );
Старший байт возвращаемого функцией значения определяет верхнюю, а младший - нижнюю границы курсора. Функция возвращает величину -1, если призошла ошибка, например, если функция вызвана в графическом режиме (графический режим работы видеоадаптеров курсор не использует).
Для установки формы курсора, удобно использовать функцию _settextcursor() из стандартной библиотеки трансляторов Microsoft Quick C 2.5 и C 6.0. Фактически функция реализована через функцию 01h прерывания 10h.
Формат функции приведен ниже:
short _settextcursor( short shape);
Параметр shape задает новую форму курсора. Старший байт определяет верхную, а младший - нижную границы курсора (см. INT 10h, функция 01h).
Возвращаемая функцией величина определяет предыдущую форму курсора, или если она равна -1 - сообщает об ошибке.
Следующий пример демонстрирует использование функций _gettextcursor() и _settextcursor():
#include <stdio.h> #include <graph.h> void main(void) { short old_cursor; char top = 0, bottom = 0; int error; // запоминаем текущую форму курсора old_cursor = _gettextcursor(); _displaycursor( _GCURSORON ); // если вводится отрицательное значение для любой границы, // то программа завершается for(;top >= 0 && bottom >= 0 ;) { // очищаем экран дисплея _clearscreen( _GCLEARSCREEN ); printf("Введите верхнюю границу курсора:"); scanf("%d", &top); printf("Введите нижнюю границу курсора:"); scanf("%d", &bottom); // изменение формы курсора error = _settextcursor((top << 8) | bottom); _clearscreen( _GCLEARSCREEN ); if( error == -1) puts("Ошибка."); else printf("Предыдущая форма курсора:" "\n верхняя граница = %d," "\n нижняя граница = %d.", error >> 8, error & 0xFF); // ожидаем нажатия на клавиатуру getch(); } // восстанавливаем прежнюю форму курсора _settextcursor( old_cursor ); }
Определить положение курсора на экране можно при помощи прерывания INT 10h, функции 03h, или, что более удобно, вызвав функцию _gettextposition():
struct rccoord _gettextposition( void );
Функция возвращает в структуре rccoord текущие координаты курсора. Заметим, что начало координат находится в левом верхнем углу экрана, имеющем координаты (1,1), ось X направлена вправо, а ось Y вниз.
Структура rccoord определена во включаемом файле graph.h следующим образом:
struct rccoord { short row; // Y координата курсора (строка) short col; // X координата курсора (столбец) };
Как и функция 02h прерывания INT 10h, функция _settextposition() из стандартной библиотеки трансляторов Microsoft Quick C 2.5 и C 6.0 управляет положением курсора на экране:
struct rccoord _settextposition( short row, short column );
Параметры функции задают новое положение курсора на экране: первый параметр - row задает строку (Y координата), а второй параметр - column задает колонку (X координата).
Функция возвращет в структуре rccoord предыдущие координаты курсора (см. функцию _gettextposition()).
Ниже приведен пример использования функций _gettextposition() и _settextposition():
#include <stdio.h> #include <graph.h> void main(void) { short i, j; struct rccoord old_cur_pos; // сохраняем старые координаты курсора old_cur_pos = _gettextposition(); _clearscreen(_GCLEARSCREEN); for(i = 0; i < 9; i++) for(j = 0; j < 12; j++){ // изменяем координаты курсора _settextposition(2*j+1, 9*i+1); printf(".(%d,%d)", 9*i+1, 2*j+1); } getch(); // восстанавливаем положение курсора _settextposition(old_cur_pos.row, old_cur_pos.col); _clearscreen(_GCLEARSCREEN); }
Функция позволяет узнать текущий цвет фона символов (см. биты D4-D6 байта атрибутов):
long _getbkcolor( void );
В текстовом режиме функция возвращает индекс цвета, а в графическом - универсальное значение цвета:
Индекс Константа Цвет (универсальное значение) 0 _BLACK черный 1 _BLUE голубой 2 _GREEN зеленый 3 _CYAN синий 4 _RED красный 5 _MAGENTA малиновый 6 _BROWN коричневый 7 _WHITE белый 8 _GRAY серый 9 _LIGHTBLUE светло-голубой 10 _LIGHTGREEN светло-зеленый 11 _LIGHTCYAN светло-синий 12 _LIGHTRED светло-красный 13 _LIGHTMAGENTA светло-малиновый 14 _YELLOW желтый 15 _BRIGHTWHITE интенсивно-белый
Таблица 15.1 Значения цветов.
Функция изменяет цвет фона выводимых символов. Прототип функции приведен ниже:
long _setbkcolor( long color );
В текстовых режимах параметр color должен содержать индекс устанавливаемого цвета фона (см. таблицу 15.1). Например, если палитра устанавливаемая по умолчанию не изменялась, то чтобы напечатать символы на красном фоне, надо вызвать функцию _setbkcolor( 4L ). При использовании функции фон отображенных ранее символов не изменяется.
В графических режимах параметр color должен содержать константу, соответствующую устанавливаемому цвету (см. таблицу 15.1). Например, если палитра устанавливаемая по умолчанию не изменялась, то чтобы напечатать символы на красном фоне, надо вызвать функцию _setbkcolor( _RED ). Константы определены во включаемом файле graph.h следующим образом:
// универсальные цветовые значения #define _BLACK 0x000000L // черный #define _BLUE 0x2a0000L // голубой #define _GREEN 0x002a00L // зеленый #define _CYAN 0x2a2a00L // синий #define _RED 0x00002aL // красный #define _MAGENTA 0x2a002aL // малиновый #define _BROWN 0x00152aL // коричневый #define _WHITE 0x2a2a2aL // белый #define _GRAY 0x151515L // серый #define _LIGHTBLUE 0x3F1515L // светло-голубой #define _LIGHTGREEN 0x153f15L // светло-зеленый #define _LIGHTCYAN 0x3f3f15L // светло-синий #define _LIGHTRED 0x15153fL // светло-красный #define _LIGHTMAGENTA 0x3f153fL // светло-малиновый #define _YELLOW 0x153f3fL // желтый #define _BRIGHTWHITE 0x3f3f3fL // интенсивно-белый #define _LIGHTYELLOW _YELLOW
Данные константы представляют цвета в формате, соответствующем регистрам таблицы цветов цифро-аналогового преобразователя адаптера VGA. Каждая константа состоит из трех байт, причем у каждого байта только шесть младших байта значащие.
Следует особо подчеркнуть, что в текстовом режиме после вызова функции цвет фона уже выведенных символов не изменяется, а в графическом режиме сразу меняется цвет всех фоновых символов экрана.
В текстовом режиме функция _setbkcolor() возвращает старый индекс цвета фона, а в графическом - универсальное значение цвета фона (см. таблицу 15.1).
С помощью этой функции можно узнать текущй цвет символов:
short _gettextcolor( void );
Функция возвращает индекс цвета символов (см. таблицу 15.1), выводимых функцией _outtext(). Для изменения цвета символов используйте функцию _settextcolor().
Функция устанавливает цвет символов, выводимых функцией _outtext():
short _settextcolor( short index );
Параметр содержит индекс нового цвета символов из таблицы 15.1. Если к номеру индекса прибавить 0x10, то выводимые символы будут мигать.
Функция возвращает предыдущий индекс цвета символов.
Ниже приведен пример использования функций определения и установки цвета фона и цвета текста _getbkcolor(), _setbkcolor(), _gettextcolor(), _settextcolor():
// Пример использования функций _getbkcolor(), _setbkcolor(), // _gettextcolor(), _settextcolor(). #include <conio.h> #include <stdio.h> #include <graph.h> void main(void) { char buffer[80]; short text_color, old_text_color; long background_color, old_background_color; struct rccoord old_pos; // сохраняем текущие цвета символов и фона, // а также положение курсора old_text_color = _gettextcolor(); old_background_color = _getbkcolor(); old_pos = _gettextposition(); // очищаем экран _clearscreen( _GCLEARSCREEN ); // устанавливаем по очереди первые 25 из 32 возможных цветов фона for(background_color = 0; background_color < 26; background_color++) { _setbkcolor(background_color ); _settextposition((short)background_color, 1); _settextcolor(_BRIGHTWHITE); sprintf(buffer, "Фон: %3d. Текст:", background_color); _outtext(buffer); // устанавливаем по очереди первые 23 из 32 возможных цветов текста for(text_color = 0; text_color < 24; text_color++) { _settextcolor(text_color); sprintf(buffer, " %d", text_color); _outtext(buffer); } } getch(); // восстанавливаем цвета символов и фона, // а также позицию курсора _settextcolor(old_text_color); _setbkcolor(old_background_color); _clearscreen(_GCLEARSCREEN); _settextposition(old_pos.row, old_pos.col); }
Функция выводит на экран строку символов в любом режиме работы видеоадаптера. Формат функции имеет следующий вид:
void _outtext( unsigned char _far *text );
Единственный параметр функции содержит указатель на выводимую строку, оканчивающуюся двоичным нулем. Строка начинает отображаться на экране с текущей позиции курсора. Символы изображаются цветом, задаваемым функцией _settextcolor().
Функции применяются, для управления видеоадаптерами в режимах с несколькими страницами видеопамяти. Они обеспечивают возможность подготовки изображения на неактивной странице видеопамяти, а затем быстрого его вывода на экран.
Функция _setactivepage() направляет вывод информаци в определенную страницу видеопамяти, а функция _setvisualpage() задает страницу, которая отображается в данный момент на экране. Функции управления страницами видеопамяти могут использоваться совместно с функциями _gettextcursor(), _settextcursor(), _settextposition(), _gettextposition(), _outtext(), _gettextcolor(), _settextcolor(), _settextwindow().
Функция управления страницами видеопамяти имеет следующий прототип:
short _setactivepage( short page );
Параметр функции задает активную страницу, в которую будет направлен весь последующий вывод.
Если функция выполнилась успешно, то она возвращает номер предыдущей активной страницы. При возникновении ошибки возвращаемая величина равна -1. Ошибка может произойти в случае задания номера страницы видеопамяти, не поддерживаемого адаптером в данном режиме.
Приведем прототип функции:
short _setvisualpage( short page );
Параметр функции задает номер страницы, отображаемой на экране дисплея. Функция возвращает номер предыдущей отображаемой страницы. При возникновении ошибки возвращаемая величина равна -1. Ошибка может произойти, например, в случае задания номера страницы видеопамяти, не поддержиеваемой адаптером. Смена отображаемой страницы в этом случае не происходит.
short _getactivepage( void );
Функция _getactivepage() возвращает номер текущей активной страницы видеопамяти.
Следующая функция, _getvisualpage(), возвращает номер страницы видеопамяти, отображаемой на экране дисплея в данный момент. Ее прототип:
short _getvisualpage( void );
В приведенном ниже примере определяется число страниц видеопамяти, в каждую страницу записывается ее номер и затем по очереди отображаются все страницы экрана.
// Пример использования функций _setactivepage(), _setvisualpage(), // _getactivepage() и _getvisualpage(). #include <stdlib.h> #include <graph.h> #include <time.h> void main(void) { short old_vpage, old_apage, page, row; struct videoconfig vc; char buffer[80]; long wait = 0; clock_t end; // определяем конфигурацию видеосистемы _getvideoconfig(&vc); // завершаем программу, если поддерживается только одна // страница видеопамяти if(vc.numvideopages<2) exit(1); // сохраняем номера активной и отображаемой страниц видеопамяти old_apage = _getactivepage(); old_vpage = _getvisualpage(); // записываем на каждой из страниц ее номер for(page = 0; page < vc.numvideopages; page++) { // изменяем активную страницу видеопамяти _setactivepage(page); _clearscreen(_GCLEARSCREEN); sprintf(buffer, "страница видеопамяти номер %d", page); for(row = page + 1; row < 26; row += vc.numvideopages) { _settextposition(row, 35); _outtext(buffer); } } while(!kbhit()) for(page = 0; page < vc.numvideopages; page++) { // меняем отображаемую страницу видеопамяти _setvisualpage(page); // производим постепенно увеличивающуюся задержку for(end = clock() + wait++; clock() < end;); } getch(); // восстанавливаем активную и отображаемую страницы _setactivepage(old_apage); _setvisualpage(old_vpage); }
Это одна из наиболее важных функций. Она позволяет изменить режим работы видеоадаптера. Ее формат имеет следующий вид:
short _setvideomode( short mode );
Параметр функции - mode - определяет новый режим и может быть равен одной из констант, представленных в таблице 15.2. Данные константы определены во включаемом файле graph.h.
Константа Режим Характеристики _TEXTBW40 0, 1 текстовый, 40x25, 16 градаций серого цвета _TEXTC40 0, 1 текстовый, 40x25, 16 цветов _TEXTBW80 2, 3 текстовый, 80x25, 16 градаций серого цвета _TEXTC80 0, 1 текстовый, 80x25, 16 цветов _MRES4COLOR 4, 5 графический, 320x200, 4 цвета _MRESNOCOLOR 4, 5 графический, 320x200, 4 градации серого цвета _HRESBW 6 графический, 640x200, 2 градации серого цвета _TEXTMONO текстовый, 80x25, монохромный _HERCMONO Hercules графический, 720x348, монохромный _MRES16COLOR 0Dh графический, 320x200, 16 цветов _HRES16COLOR 0Eh графический, 640x200, 16 цветов _ERESNOCOLOR 0Fh графический, 640x350, монохромный _ERESCOLOR 10h графический, 640x350, 16 цветов _VRES2COLOR 11h графический, 640x480, 2 цвета _VRES16COLOR 12h графический, 640x480, 16 цветов _MRES256COLOR 13h графический, 320x200, 256 цветов _ORESCOLOR Olivetti графический, 640x400, 1 из 16 видеоадаптер фирмы Olivetti _DEFAULTMODE режим, используемый видеоадаптером по умолчанию _MAXRESMODE графический режим с наивысшим разрешением доступным на данном видеоадаптере _MAXCOLORMODE графический режим с наибольшим числом цветов поддерживаемых видеоадаптером
Таблица 15.2 Режимы работы видеоадаптеров.
Характеристики последних трех режимов, перечисленных в таблице, зависят от типа используемого видеоадаптера и дисплея.
Функция _setvideomode() возвращает число текстовых строк в установленном режиме работы видеоадаптера. Если произошла ошибка, например запрашиваемый режим не поддерживается видеоадаптером, функция возвращает ноль.
В таблице 15.3 перечислены режимы, используемые для констант _MAXRESMODE и _MAXCOLORMODE в зависимости от конфигурации видеоситемы.
Видеоадаптер _MAXRESMODE _MAXCOLORMODE дисплей MDA нет нет Hercules _HERCMONO _HERCMONO CGA с CD _HRESBW _MRES4COLOR CGA с MD _HRESBW _MRESNOCOLOR OCGA (фирма _ORESCOLOR _MRES4COLOR Olivetti) OCGA с CD _ORESCOLOR _ERESCOLOR EGA (256K) с CD _HRES16COLOR _HRES16COLOR EGA (64K) с CD _HRES16COLOR _HRES16COLOR EGA(256K) с ECD _ERESCOLOR _ERESCOLOR EGA (64K) с ECD _ERESCOLOR _HRES16COLOR EGA с MD _ERESNOCOLOR _ERESNOCOLOR MCGA _VRES2COLOR _MRES256COLOR VGA _VRES16COLOR _MRES256COLOR OVGA (фирма _VRES16COLOR _MRES256COLOR Olivetti)
Таблица 15.3 Режимы _MAXRESMODE и _MAXCOLORMODE.
Режимы TEXTC40, TEXTBW40 и TEXTC80, TEXTBW80 различаются только используемой цветовой палитрой. В режимах TEXTBW40 и TEXTBW80 могут отображаться только градации серого цвета.
Видеоадаптер Hercules может работать в режиме _HERCMONO. Это монохромный режим с разрешением 720x348 пикселов. Он обеспечивает отображение 25 текстовых строк по 80 символов в каждой. При этом матрица символов имеет размер 9x14 пикселов.
Перед исполнением вашей программы в режиме _HERCMONO надо установить специальный драйвер видеоадаптера Hercules - программу msherc.com. Программу msherc.com можно запустить либо перед выполнением прикладной программы, либо непосредственно из нее (напрмер запустив ее при помощи функций system или exec).
При одновременном использовании видеоадаптеров Hercules и EGA, надо запускать программу msherc.com с ключом /H (Half - половина). После этого видеоадаптер Hercules будет использовать только одну из двух страниц видеопамяти, что позволяет избежать конфликтов между видеоадаптерами.
Теперь приведем простой пример, использующий функцию _setvideomode. Программа сначала пытается перевести видеоадаптер в цветной графический режим _MRES16COLOR, а если адаптер его не поддерживает, то в режим _MRES4COLOR с такой же разрешающей способностью, но меньшим числом цветов.
// Пример использования функций _setvideomode() и _outtext(). #include <conio.h> #include <graph.h> void main(void) { // пытаемся установить режим _MRES16COLOR if(_setvideomode(_MRES16COLOR)) _outtext("установлен режим _MRES16COLOR"); // пытаемся установить режим _MRES4COLOR else if(_setvideomode(_MRES4COLOR)) _outtext("установлен режим _MRES4COLOR"); else _outtext("Адаптер не поддерживает режимы\n" "_MRES16COLOR and _MRES4COLOR mode."); getch(); // восстанавливаем режим, используемый адаптером по умолчанию _setvideomode( _DEFAULTMODE ); }
Функция выполняет очистку отдельной области или всего экрана дисплея. Очищаемая область закрашивается текущим цветом фона. Функция имеет следующий прототип:
void _clearscreen( short area );
Параметр area может быть равен одной из следующих констант, определенных в файле graph.h:
Константа Производится очистка _GCLEARSCREEN всего экрана _GVIEWPORT текукщей логической системы координат _GWINDOW текущего текстового окна
Функция задает окно на экране дисплея, в котором будет помещаться вся выводимая текстовая информация.
Вывод текста в окно происходит сверху вниз. После заполнения всего окна его содержимое автоматически прокручивается (свертывается) вверх.
Функция _settextwindow() не воздействует на выполнение функции _outtext() (для этого надо воспользоваться функцией _setviewport()).
Приведем прототип функции:
void _settextwindow( short y_up, short x_left, short y_down, short x_right );
Параметры (x_left, y_up) определяют верхний левый угол окна, а параметры (x_right, y_down) - правый нижний угол относительно верхнего левого угла экрана.
Работу функции иллюстрирует следующий пример:
// Пример использования функции _settextwindow(). #include <time.h> #include <stdio.h> #include <conio.h> #include <graph.h> void main(void) { clock_t end, wait = 0; _clearscreen(_GCLEARSCREEN); // определяем окно в центре экрана _settextwindow(8, 34, 17, 46); // функция _settextposition() задает координаты курсора // относительно левого верхнего угла окна _settextposition(5, 5); // функция _outtext() осуществляет запись строк символов в окно while(!kbhit()) { _outtext("0123456789"); for(end = clock() + wait++; clock() < end;); } _settextwindow(10, 36, 15, 44); // очищаем новое окно _clearscreen(_GWINDOW); _settextposition(3, 4); printf("End!"); }