
- •Глава 12 графика
- •1. Общие сведения
- •2. Инициализация графической системы. Обработка ошибок. Переключение режимов
- •Initgraph (&gd, &gm,"путь к bgi-файлам");
- •3. Работа с окнами и координатами
- •4. Графические примитивы
- •1 Способ:
- •2 Способ:
- •5. Включение .Bgi-драйверов в .Exe-файл
- •Примеры решения задач Задача a
- •Задание для самостоятельной работы
- •Задача b
- •Задание для самостоятельной работы
- •Задача c
- •Задание на программирование Задача 1
- •Задача 2
- •Задача 3
- •Задача 4
- •Задача 5
- •Задача 6
- •Задача 7
- •Задача 8
- •Задача 9
- •Задача 14
- •Задача 15
- •Задача 16
- •Задача 17
- •Задача 29
- •Задача 37
- •Задача 39
- •Задача 40
5. Включение .Bgi-драйверов в .Exe-файл
Обычно .BGI-драйвер не является частью кода программы, а загружается как программный оверлей во время выполнения функции initgraph() (т.е. имеет место динамическая загрузка). И поэтому, чтобы программа с графикой могла работать, необходимо всегда "таскать за собой" вместе с .EXE-файлом еще и нужные .BGI-драйверы, причем, помещать их всегда в определенную директорию (которая указана при вызове initgraph()). Естественно, это не очень удобно, например, при переносе программы.
В TC++ предусмотрена возможность встраивания в .EXE-файл .BGI-драйвера, т.е., его статическое включение в программу на этапе компоновки. Для этого необходимо выполнить следующие три действия:
1) Превратить бинарный файл драйвера .BGI в обычный файл типа .OBJ. Это преобразование осуществляется с помощью утилиты BGIOBJ.exe (надо набрать в командной строке имя этой утилиты и рядом - имя нужного .BGI-файла; в результате будет порожден файл с именем, например, вместо EGAVGA.BGI - EGAVGA.OBJ).
2) Сообщить графической системе, что драйвер уже находится в оперативной памяти, и не требуется его загрузка с диска. Для этого в графической библиотеке предусмотрена функция
int registerbgidriver(void (*driver)(void))
(аргументом является имя регистрируемого драйвера, например, EGAVGA_driver). Эта функция должна быть вызвана перед инициализацией графической системы. В случае ошибки будет возвращено целое число <0.
3) Cкомпоновать программу вместе с объектным файлом драйвера. Это можно сделать одним из следующих способов:
а) создать файл проекта, куда поместить имя исходного файла на С и .OBJ-файл, полученный из .BGI-файла;
б) перечислить эти файлы в командной строке компилятора TCC или компоновщика TLINK;
в) с помощью утилиты TLIB включить .OBJ-файл в графическую библиотеку GRAPHICS.LIB, откуда компоновщик возьмет его автоматически.
При статическом включении драйвера в программу не тратится время на чтение .BGI-файла с диска (значит, при выполнении программы этих файлов на диске может и не быть). Однако, вырастает начальный размер программы, и ОП расходуется не оптимально, так как даже если программа в данный момент не работает с графической системой, драйвер все равно находится в памяти.
Примеры решения задач Задача a
Изобразить на экране прямоугольник и обеспечить возможность его передвижения с помощью клавиш управления курсором.
// Возможно, на Вашей машине необходимо изменить значение BGIPATH.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <graphics.h>
#define BGIPATH "c:\\borlandc\\bgi" //Директория, содержащая файлы *.bgi
#define ESC 27 // Коды клавиш, возвращаемые getch()
#define UP_ARROW 72
#define DOWN_ARROW 80
#define RIGHT_ARROW 77
#define LEFT_ARROW 75
void Initialize ();
void MoveRec ();
int GraphDriver; // Номер драйвера
int GraphMode; // Номер графического режима
int MaxX, MaxY; // Максимальное разрешение экрана
int MaxColors; // Максимальное доступное число цветов
int ErrorCode; // Код завершения графической функции
void main ()
{
Initialize ();
MoveRec ();
closegraph ();
}
void Initialize ()
{
detectgraph (&GraphDriver, &GraphMode);
initgraph (&GraphDriver, &GraphMode, BGIPATH);
ErrorCode = graphresult ();
if ( ErrorCode != grOk )
{
printf ("Ошибка инициализации: %s\n",
grapherrormsg ( ErrorCode ) );
exit (1);
}
// Определяем максимальное число цветов
MaxColors = getmaxcolor () + 1;
// Определяем размер экрана
MaxX = getmaxx ();
MaxY = getmaxy ();
}
void MoveRec ()
{
int i, x, y, x1, y1, x2, y2;
int scalex=1, scaley=1;
setbkcolor (BLUE);
setfillstyle (1, WHITE);
// Изобразить прямоугольник в центре экрана - начальная позиция
x1=MaxX/2-70; y1=MaxY/2-20;
x2=MaxX/2+70;
y2=MaxY/2+20;
bar (x1, y1, x2, y2);
// Ожидать нажатия клавиши. Выход при нажатии клавиши <ESC>
for (i=getch(); i != ESC; i=getch())
{
if (i) continue; // Алфавитно-цифровая клавиша
switch (getch ())
{
case UP_ARROW : x=0; y=-1; break;
case DOWN_ARROW : x=0; y=1; break;
case RIGHT_ARROW : x=1; y=0; break;
case LEFT_ARROW : x=-1; y=0; break;
default : continue;
}
// Не вышли ли за границу экрана?
if( (x1+x*scalex<0) || (x2+x*scalex>MaxX) ) x=0;
if( (y1+y*scaley<0) || (y2+y*scaley>MaxY) ) y=0;
// Удалить старое изображение - закрасить цветом фона
setfillstyle (1, BLUE); bar (x1, y1, x2, y2);
// Нарисовать прямоугольник в новых координатах, используя масштабирование
setfillstyle (1, RED);
x1+=x*scalex; x2+=x*scalex; y1+=y*scaley; y2+=y*scaley;
bar (x1, y1, x2, y2);
}
}