Глава знакомит читателей с основными функциями стандартной библиотеки трансляторов Microsoft Quick C 2.5 и C 6.0, предназначенными для управления экраном дисплея в текстовом режиме. Глава содержит описание функций, управляющих формой и координатами курсора, текущим режимом работы видеоадаптера и переключением страниц видеопамяти, отображением текста и изменением цвета символов и цвета фона.

14.1. Функция _displaycursor()

Функция позволяет в текстовых режимах видеоадаптеров погасить курсор. Приведем ее прототип:

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();
}

14.2. Функция _gettextcursor()

Функция позволяет определить форму курсора, тоесть положение его верхней и нижней границы:

short _gettextcursor( void );

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

14.3. Функция _settextcursor()

Для установки формы курсора, удобно использовать функцию _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 );
}

14.4. Функция _gettextposition()

Определить положение курсора на экране можно при помощи прерывания INT 10h, функции 03h, или, что более удобно, вызвав функцию _gettextposition():

struct rccoord _gettextposition( void );

Функция возвращает в структуре rccoord текущие координаты курсора. Заметим, что начало координат находится в левом верхнем углу экрана, имеющем координаты (1,1), ось X направлена вправо, а ось Y вниз.

Структура rccoord определена во включаемом файле graph.h следующим образом:

struct rccoord {

      short row;   // Y координата курсора (строка)
      short col;   // X координата курсора (столбец)
};

14.5. Функция _settextposition()

Как и функция 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);
}

14.6. Функция _getbkcolor()

Функция позволяет узнать текущий цвет фона символов (см. биты 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 Значения цветов.

14.7. Функция _setbkcolor()

Функция изменяет цвет фона выводимых символов. Прототип функции приведен ниже:

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).

14.8. Функция _gettextcolor()

С помощью этой функции можно узнать текущй цвет символов:

short _gettextcolor( void );

Функция возвращает индекс цвета символов (см. таблицу 15.1), выводимых функцией _outtext(). Для изменения цвета символов используйте функцию _settextcolor().

14.9. Функция _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);
}

14.10. Функция _outtext()

Функция выводит на экран строку символов в любом режиме работы видеоадаптера. Формат функции имеет следующий вид:

void _outtext( unsigned char _far *text );

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

14.11. Функции _setactivepage(), _setvisualpage(), _getactivepage() и _getvisualpage()

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

Функция _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);
}

14.12. Функция _setvideomode()

Это одна из наиболее важных функций. Она позволяет изменить режим работы видеоадаптера. Ее формат имеет следующий вид:

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 );
}

14.13. Функция _clearscreen()

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

void _clearscreen( short area );

Параметр area может быть равен одной из следующих констант, определенных в файле graph.h:

Константа       Производится очистка

_GCLEARSCREEN   всего экрана
_GVIEWPORT      текукщей логической системы координат
_GWINDOW        текущего текстового окна

14.14. Функция _settextwindow()

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

Вывод текста в окно происходит сверху вниз. После заполнения всего окна его содержимое автоматически прокручивается (свертывается) вверх.

Функция _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!");
}