Глава знакомит читателей с основными функциями стандартной графической библиотеки трансляторов Microsoft Quick C 2.5 и C 6.0. Функции, описанные в этой главе, предоставляют программисту разнообразные возможности управления графическим экраном дисплея.
Описаны функции отображения простых графических объектов, таких как точка, прямая, эллипс, прямоугольник, функции, управляющие системой координат, а также функции, применяемые для сохранения и вывода на экран прямоугольных областей экрана (спрайтов).
Каждая группа функций сопровождается примерами программ.
Функция устанавливает цвет пиксела в заданной позиции экрана. Приведем прототип этой функции:
short _setpixel( short x, short y );
Цвет пиксела устанавливается предварительно функцией _setcolor(). Координаты пиксела задаются параметрами x и y.
Функция возвращает предыдущий цвет пиксела или -1, если произошла ошибка.
Функция рисует на экране линию. Ее прототип приведен ниже:
short _lineto( short x_target, short y_target );
Линия начинается в текущей точке и заканчивается в точке, имеющей координаты (x_target, y_target). После отображения линии координаты текущей точки становяться равными (x_target, y_target). Для изменения координат текущей точки можно воспользоваться функцией _lineto().
Линия изображается в текущем цвете (функция _setcolor()) и текущем стиле (функция _setstyle()).
Как и все уже рассмотренные функции, функция _lineto() возвращает ненулевую величину, если она выполнилась успешно и ноль, если произошла ошибка.
Функция изменяет положение текущей точки. Используется совместно с _lineto() для изображения линий. Прототип функции _moveto() имеет следующий вид:
struct xycoord _moveto( short x, short y );
Новые координаты текущей точки соответствуют параметрам функции (точка с координатами (x,y)).
Функция возвращает в структуре xycoord координаты предыдущей точки. Структура xycoord определена в файле graph.h следующим образом:
struct xycoord { short xcoord ; // x координата точки short ycoord ; // y координата точки };
Функция рисует прямоугольник. В зависимости от параметров функции прямоугольник может быть закрашенным или не закрашенным. Прототип функции имеет следующий вид:
short _rectangle( short fill, short x_left, short y_top, short x_right, short y_bottom );
Прямоугольник определяетя координатами любых двух противоположных углов (x_left,y_top) и (x_right,y_bottom).
Граница прямоугольника изображается текущим цветом с использованием текущего стиля. Если например fill равен _GFILLINTERIOR, то прямоугольник закрашивается, а если _GBORDER - то не закрашивается. Для изменения текущего цвета используют функцию _setcolor().
Функция возвращает ненулевую величину, если она выполнилась успешно и ноль, если произошла ошибка.
Следующая программа иллюстрирует использование функций _moveto(), _lineto() и __rectangle():
#include <conio.h> #include <stdlib.h> #include <stdio.h> #include <graph.h> // макроопределение, ранжирующее величину, возвращаемую // генератором случайных чисел (rand) в интервале от 0 // до max #define random(max) (rand() % (int)((max)+1)) void main(void) { short x, y; short color; struct videoconfig vc; // устанавливаем графический режим с максимальным числом цветов if(!_setvideomode(_MAXCOLORMODE)) { puts("Видеоадаптер не поддерживает графический режим."); exit(1); } // получаем информацию о конфигурации видеосистемы и об // установленном режиме работы видеоадаптера _getvideoconfig(&vc); while(!kbhit()) { // устанавливаем произвольный допустимый цвет, который // используется при изображении графических объектов _setcolor((short)random(vc.numcolors)); // выбираем произвольную точку экрана - (x,y) x = (short)random(vc.numxpixels), y = (short)random(vc.numypixels); // рисуем закрашенный и незакрашенный прямоугольники _rectangle(_GFILLINTERIOR, x + 30, y + 40, x, y); _rectangle(_GBORDER, x + 40, y + 30, x, y); } // ожидаем нажатие на клавиатуру getch(); // помещаем текущую точку в центр экрана _moveto(vc.numxpixels/2, vc.numypixels/2); while(!kbhit()) { _setcolor((short)random(vc.numcolors)); x = (short)random(vc.numxpixels), y = (short)random(vc.numypixels); // рисуем линию из центра экрана в произвольную точку экрана _lineto(x, y); _moveto(vc.numxpixels/2, vc.numypixels/2); } getch(); // устанавливаем режим видеоадаптера, принятый по умолчанию _setvideomode(_DEFAULTMODE); }
Функция рисует эллипс. Приведем прототип этой функции:
short _ellipse( short fill, short x_left, short y_top, short x_right, short y_bottom );
Эллипс задается прямоугольником, в который он вписан. Прямоугольник определяется координатами любых двух противоположных углов (x_left,y_top) и (x_right,y_bottom). Работа функции иллюстрируется на рисунке 16.1.
ELLIPSE.PCX;6";2.559";PCX
Рисунок 16.1 Построение эллипса функцией _ellipse().
Граница эллипса изображается текущим цветом. Если аргумент fill функции равен _GFILLINTERIOR, то эллипс закрашивается, а если _GBORDER - то не закрашивается. Для изменения текущего цвета используют функцию _setcolor().
Если аргументы функции определяют вертикальную или горизонтальную линии или же точку, то эллипс не рисуется.
Функция возвращает не нулевую величину, если она выполнилась успешно и ноль, если произошла ошибка.
Функция рисует дугу эллипса.
Прототип функции _arc() имеет следующий вид:
short _arc( short x_left, short y_top, short x_right, short y_bottom, short x_begin, short y_begin, short x_end, short y_end );
Эллипс задается прямоугольником, в который он вписан. Прямоугольник определяетя координатами любых двух противоположных углов (x_left, y_top) и (x_right, y_bottom). Дуга строится от точки пересечения эллипса с прямой, соединяющей центр эллипса с точкой (x_begin, y_begin) до точки пересечения эллипса прямой, соединяющей его центр с точкой (x_end, y_end) против часовой стрелки (см. рисунок 16.2).
ARC.PCX;6";3.439";PCX
Рисунок 16.2 Построение дуги эллипса функцией _arc().
Функция возвращает ненулевую величину, если она выполнилась успешно и ноль, если произошла ошибка.
Функция рисует сектор эллипса:
short _pie( short fill, short x_left, short y_top, short x_right, short y_bottom, short x_begin, short y_begin, short x_end, short y_end );
Эллипс задается прямоугольником, в который он вписан. Прямоугольник определяетя координатами любых двух противополжных углов (x_left, y_top) и (x_right, y_bottom). Дуга сектора строится от точки пересечения эллипса с прямой, соединяющей центр эллипса с точкой (x_begin, y_begin) до точки пересечения эллипса прямой, соединяющей его центр с точкой (x_end, y_end) против часовой стрелки (см. рисунок 16.3).
PIE.PCX;6";3.439";PCX
Рисунок 16.3 Построение сектора эллипса при помоши функции _pie().
Граница эллипса изображается текущим цветом. Если поле fill равно _GFILLINTERIOR, то эллипс закрашивается, а если _GBORDER - то не закрашивается. Для изменения текущего цвета используют функцию _setcolor().
Функция возвращает ненулевую величину, если она выполнилась успешно и ноль, если произошла ошибка.
В графическом режиме видеоадаптера функция _setcolor() устанавливает текущий цвет, используемый функциями _setpixel(), _lineto(), _rectangle(), _ellipse(), _arc(), _pie().
Прототип функции _setcolor() приведен ниже:
short _setcolor( short color );
Параметр color должен содержать индекс цвета. По умолчанию используется цвет с наибольшим индексом в палитре цветов.
Функция возвращает предыдущий индекс цвета. В случае ошибки функция возвращает -1.
Функция изменяет цветовую палитру для режимов _MRES4COLOR и _MRESNOCOLOR. В этих режимах цветовая палитра содержит четыре цвета - цвет фона, выбираемый отдельно и три цвета, устанавливаемых функцией _selectpalette(). Функция имеет следующий прототип:
short _selectpalette( short palette_number );
Единственный параметр функции имеет различное значение в разных режимах видеоадаптера.
В режиме _MRES4COLOR параметр palette_number выбирает одну из четырех возможных цветовых палитр:
Номер палитры Индекс 1 Индекс 2 Индекс 3 (palette_number) 0 зеленый красный коричневый 1 синий малиновый светло- серый 2 светло- светло- желтый зеленый красный 3 светло- светло- белый синий малиновый
В режиме _MRESNOCOLOR, для видеоадаптера CGA с цветным дисплеем используется следующая цветовая палитра:
Номер палитры Индекс 1 Индекс 2 Индекс 3 (palette_number) 0 голубой красный светло- серый 1 светло- светло- белый голубой красный
Если вместо адаптера CGA подключен EGA, то доступны три цветовых палитры:
Номер палитры Индекс 1 Индекс 2 Индекс 3 (palette_number) 0 зеленый красный коричневый 2 светло- светло- желтый зеленый красный 3 светло- светло- желтый синий красный
Функция _selectpalette() возвращает номер предыдущей используемой цветовой палитры.
Функция определяет маску, используемую при рисовании линий функцией _lineto():
void _setlinestyle( unsigned short mask );
Единственный параметр функции является набором из 16 бит. Каждый бит соответствует пикселу на отображаемой линии. При этом если бит параметра равен единице, то соответствующий ему пиксел на линии отображается текущим цветом. А если бит параметра равен нулю, то пиксел не отбражается.
Если функция _setlinestyle() не вызывалась, то по умолчанию маска равна 0xFFFF, и, следовательно, все пикселы линии отображаются на экране.
Мы будем использовать две различные системы координат - физическую и логическую.
Начало физической системы координат находится в левом верхнем углу экрана дисплея. Оси координат x и y направлены соответственно слева направо и сверху вниз.
Логическая система координат представляет собой прямоугольную область. Ее начало координат расположено в левом верхнем углу прямоугольной области, а оси координат направлены следующим образом: одна - вправо, другая - вниз. По умолчанию, логическая система координат совпадает с физической. Для ее изменения предназначены функции _setviewport() и _setvieworg(). Подавляющее большинство основных графических функций стандартной библиотеки трансляторов Microsoft Quick C 2.5 и C 6.0 применяют логическую систему координат.
Прототип функции _setviewport() приведен ниже:
void _setviewport( short x_first, short y_first, short x_second, short y_second );
Параметры функции x_first, y_first и x_second, y_second задают прямоугольную область экрана, в которую направляется последующий вывод графической информации. При этом верхний левый угол области является началом координат созданной логической системы координат.
Функция перемещает начало логических координат (точку (0, 0)) в точку экрана, имеющую физические координаты (x, y). Прототип функции имеет следующий вид:
struct xycoord _setvieworg( short x, short y );
Функция возвращает предыдущее положение начала логических координат относительно физической системы координат.
Данная функция, также как и функция _setvideomode(), позволяет изменить режим работы видеоадаптера. Но для текстовых режимов она позволяет устанвить нестандартное число строк.
Функция имеет следующий прототип:
short _setvideomoderows( short mode, short rows );
Первый параметр функции - mode, определяет режим,
в который переводится видеоадаптер. Этот
параметр может быть равен одной из следующих
констант:
_DEFAULTMODE, _ERESCOLOR, _ERESNOCOLOR, _HERCMONO, _HRES16COLOR,
_HRESBW, _MAXCOLORMODE, _MAXRESMODE, _MRES4COLOR, _MRES16COLOR, _MRES256COLOR,
_MRESNOCOLOR, _ORESCOLOR, _TEXTBW40, _TEXTBW80, _TEXTC40, _TEXTC80, _TEXTMONO,
_VRES2COLOR, _VRES16COLOR.
Эти константы описаны в таблице 16.1:
Константа Режим Характеристики _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 графический режим с наибольшим числом цветов поддерживаемых видеоадаптером
Таблица 16.1 Режимы работы видеоадаптеров.
Если устанавливается текстовый режим видеоадаптера, то второй параметр функции (rows), задает число строк на экране дисплея.
Второй параметр может быть равен константе _MAXTEXTROWS. В этом случае устанавливается максимально возможное для данной видеосистемы число строк. У видеоадаптера VGA это 50, EGA - 43, а у других адаптеров - 25 строк в текстовых режимах.
Функция возвращает число строк на экране дисплея или 0, если произошла ошибка (запрашиваемый режим не поддерживается видеоадаптером).
Функция имеет следующий прототип:
_getimage( short x_first, short y_first, short x_second, short y_second, char _huge *image );
Она записывает содержимое прямоугольной области экрана, определенной точками (x_first, y_first) и (x_second, y_second) в буфер, на который указывает параметр image. Необходимый размер буфера можно узнать при помощи функции _imagesize().
Функция имеет следующий прототип:
void _putimage( short x, short y, char _huge *image, short action );
Функция помещает пиктограмму, записанную в буфере image, на экран. При этом верхняя левая точка пиктограммы помещается в точке с координатами (x, y).
Параметр action определяет способ записи пиктограммы. В следующей таблице приведены возможные значения параметра action:
Констаната Смысл _GAND записываемая пиктограмма накладывается на область экрана так, что результат получается как логическое "И" данных пиктограммы и экрана _GOR, записываемая пиктограмма накладывается на область экрана так, что результат получается как логическое "ИЛИ" данных пиктограммы и экрана _GXOR записываемая пиктограмма накладывается на область экрана так, что результат получается как логическое "ИСКЛЮЧАЮЩЕЕ ИЛИ" данных пиктограммы и экрана _GPRESET копирует пиктограмму на экран, при этом цвет каждого пиксела инвертируется _GPSET копирует пиктограмму на экран, при этом цвет каждого пиксела сохраняется
Таблица 16.2 Различные способы записи пиктограмм.
Функция возвращает размер буфера (в байтах), необходимого для сохранения прямоугольного участка экрана дисплея, задаваемого двумя диагонально противоположными точками - (x_first, y_first) и (x_second, y_second).
long _imagesize( short x_first, short y_first, short x_second, short y_second );
Функция определяет размер буфера по следующим формулам:
width = abs(x_first-x_second) + 1; height = abs(y_first-y_second) + 1; size=((long)((width * bits_per_pixel + 7) / 8)*(long)height) + 4;
Величина bits_per_pixel, содержит число битов видеопамяти определяющих один пиксел. Этот параметр режима видеоадаптера можно получить через функцию _getvidioconfig().
После вычислений переменная size содержит необходимый размер буфера в байтах.
Теперь приведем программу, иллюстрирующую использование функций _imagesize(), _getimage() и _putimage(). Она переводит видеоадаптер в графический режим и отображает несколько строк текста. Затем она при помощи функции _getimage() записывает участок экрана в буфер памяти. Далее программа отображает этот участок в нескольких соседних местах экрана, создавая иллюзию перемещения изображения.
#include <conio.h> #include <stdlib.h> #include <malloc.h> #include <graph.h> void main(void) { char _huge *buffer; char text[8]; long imsize; short i, x = 0, width = 60, height = 27; // выбираем режим видеоадаптера с наибольшим разрешением if(!_setvideomode(_MAXRESMODE)) exit(1); sprintf(text, "текстовая строка"); // отображаем на экране несколько строк text for(i = 1; i < 8; i++) { _settextposition(i, i); _outtext(text); } // определяем размер буфера для пиктограммы высотой height // и шириой width imsize = _imagesize(0, 0, width, height); // резервируем буфер памяти для пиктограммы buffer = halloc(imsize, 1); if(buffer == NULL) exit(1); // запоминаем пиктограмму в буфере _getimage(0, 0, width, height, buffer); // перемещаем пиктограмму по экрану дисплея while(x < 400) // отображаем пиктограмму _putimage(x++, 0, buffer, _GPSET); getch(); free(buffer); }