{Адаптер ATT400:}
ATT400C0 = 0
|
{Аналог режима CGAC0}
|
ATT400C1 = 1
|
{Аналог режима CGAC1}
|
ATT400C2 = 2
|
{Аналог режима CGAC2}
|
ATT400C3 = 3
|
{Аналог режима CGAC3}
|
ATT400Med = 4
|
{Аналог режима CGAHi}
|
ATT400Hi = 5
|
{640x400, 2
цвета}
|
{Адаптер VGA:}
VGALo
= 0
|
{640x200}
|
VGAMed
= 1
|
\б40х350}:
|
VGAHi
= 2
|
{64Qx480}
|
PC3270Hi = 0
|
(Аналог HercMonoHi}
|
{Адаптер IBM8514}
IBM8514Lo = 0
|
{640x480, 256 цветов}
|
IBM8514Hi = 1
|
{1024x768, 256 цветов}
|
Пусть, например, драйвер CGA.BGI находится в каталоге TF42GI на диске С и устанавливается режим работы 320x200
с палитрой 2. Тогда обращение к процедуре будет таким:
Uses Graph;
var Driver,
Mode : Integer;
begin
Driver :=
CGA; {Драйвер}
Mode :=
CGAC2; {Режим работы}
InitGraph(Driver, Mode, 'C:\TP\BGI');
. . .
Если тип адаптера ПК
неизвестен или если программа рассчитана на работу с любым адаптером,
используется обращение к процедуре с требованием автоматического определения
типа драйвера:
Driver := Detect;
InitGraph(Driver, Mode, 'C:\TP\BGI');
После такого обращения
устанавливается графический режим работы экрана, а при выходе из процедуры
переменные Driver и Mode содержат целочисленные значения, определяющие тип
драйвера и режим его работы. При этом для адаптеров, способных работать в
нескольких режимах, выбирается старший режим, т.е. тот, что закодирован
максимальной цифрой. Так, при работе с CG^-адаптером обращение к процедуре со значением Driver = Detect вернет в переменной Driver значение 1 (CGA) и в Mode -значение 4 (CGAHi), а такое же обращение к адаптеру VGA вернет Driver = 9 flfGA) и Mode = 2 fPGAHi).
Функция GraphResult. Возвращает значение типа Integer, в котором закодирован результат последнего
обращения к графическим процедурам. Если ошибка не обнаружена, значением
функции будет ноль, в противном случае - отрицательное число, имеющее следующий
смысл:
grOk
|
= 0
|
{Нет ошибок}
|
grlnitGraph
|
= -l
|
{He инициирован графический режим}
|
grNotDetected
|
= -2
|
{Не определен тип драйвера}-
|
grFileNotFind
|
= -3
|
{Не найден графический драйвер}
|
grlnvalidDriver
|
= -4
|
{Неправильный тип драйвера}
|
grNoLoadMem
|
= -5
|
{Нет памяти для размещения
драйвера}
|
grNoScanMem
|
= -6
|
{Нет памяти для просмотра
областей}
|
grNoFloodMem
|
= -7
|
{Нет памяти для закраски областей}
|
grFontNot Found
|
= -8;
|
{He найден файл
со шрифтом}
|
grN0F0ntMem
|
= -9;
|
{Нет памяти для размещения шрифта}
|
grlnvalidMode
|
= -10
|
{Неправильный графический режим}
|
grError
|
= -ll
|
{Общая ошибка}
|
grIOError
|
= -12
|
{Ошибка ввода-вывода}
|
grlnvalidFont
|
= -13
|
{Неправильный формат шрифта}
|
grInvalidFontNum
|
=-14
|
{Неправильный номер шрифта
|
После обращения к функции GraphResult признак ошибки сбрасывается, поэтоыу повторное
обращение к ней вернет ноль.
Функция GraphErrorMsq. Возвращает значение типа String, в
котором по указанному коду ошибки дается соответствующее текстовое сообщение.
Заголовок функции:
Function
GraphErrorMsg(Code: Integer): String;
Здесь Code - код ошибки, возвращаемый функцией GraphResult.
Например, типичная
последовательность операторов для инициации графического режима с
автоматическим определением типа драйвера и установкой максимального разрешения
имеет следующий вид:
Var Driver, Mode, Error : Integer;
begin
Driver
:= Detect;
{Автоопределение драйвера}
InitGraph(Driver,
Mode, ''); {Инициируемграфику}
Error
:= GraphResult;
{Получаем результат}
if
Error <> grOk then {Проверяем ошибку}
begin {Ошибка в
процедуре инициации}
WriteLn(GraphErrorMsg(Error));
{Выводим сообщение}
end else
{Нет ошибки}
Чаще всего
причиной возникновения ошибки при обращении к процедуре InitGraph является неправильное указание местоположения файла
с драйвером графического адаптера (например, файла CGA.BGI для адаптера CGA). Настройка на местоположение драйвера
осуществляется заданием маршрута поиска нужного файла в имени драйвера при
вызове процедуры InitGraph. Если,
например, драйвер зарегистрирован в подкаталоге DRIVERS каталога PASCAL на диске D, то нужно использовать вызов:
InitGraph(Driver,
Mode, 'd:\Pascal\Drivers');
Замечание. Во всех следующих примерах процедура InitGraph вызывается с параметром Driver в виде пустой строки. Такая форма обращения будет
корректна только в том случае, когда нужный файл графического драйвера
находится в текущем каталоге. Для упрощения повторения примеров скопируйте
файл, соответствующий адаптеру Вашего ПК, в текущий каталог.
Процедура CloseGraph.
Завершает работу адаптера в графическом режиме и восстанавливает текстовый
режим работы экрана. Заголовок:
Procedure CloseGraph;
Процедура RestoreCRTMode.
Служит для кратковременного возврата в текстовый режим. В отличие от процедуры
CloseGraph
не сбрасываются установленные
параметры графического
режима и не освобождается память,
выделенная для размещения графического драйвера. Заголовок:
Procedure RestoreCRTMode;
Функция GetGraphMode.
Возвращает значение типа Integer, в
котором содержится код установленного режима работы графического адаптера.
Заголовок:
Function GetGraphMode: Integer;
Процедура SetGraphMode.
Устанавливает новый графический режим работы адаптера. Заголовок:
Procedure SetGraphMode(Mode: Integer);
Здесь Mode - код устанавливаемого режима.
Следующая
программа иллюстрирует переход из графического режима в текстовый и обратно:
Uses Graph;
Var Driver,
Mode, Error : Integer;
begin
{Инициируем
графический режим}
Driver := Detect;
InitGraph(Driver,
Mode, '');
Error
:= GraphResult;
{Запоминаем результат}
if
Error <> grOk then {Проверяем ошибку}
WriteLn(GraphErrorMsg(Error))
{Есть ошибка}
else
begin
{Нет ошибки}
WriteLn
('Это графический режим'); WriteLn ('Нажмите "Enter"...':20);
ReadLn;
{Переходим в
текстовый режим} RestoreCRTMode;
WriteLn (' А это текстовый...'); ReadLn;
{Возвращаемся в графический режим} SetGraphMode (GetGraphMode); WriteLn ('Опять графический режим...'); ReadLn; CloseGraph;
end end.
В этом примере для
вывода сообщений как в графическом, так и в текстовом режиме используется
стандартная процедура WriteLn. Если
Ваш ПК оснащен нерусифицированным адаптером CGA, вывод
кириллицы в графическом режиме таким способом невозможен, в этом случае
замените соответствующие сообщения так, чтобы использовать только латинские
буквы.
Процедура DetectGraph. Возвращает тип драйвера и режим его работы.
Заголовок:
Procedure DetectGraph(var
Driver,Mode: Integer);
Здесь Driver - тип драйвера; Mode - режим работы.
В отличие от
функции GetGraphMode описываемая
процедура возвращает в переменной Mode максимально
возможный для данного адаптера номер графического режима.
Функция GetDriverName. Возвращает значение типа String, содержащее имя загруженного графического драйвера.
Заголовок:
Function GetDriverName: String;
Функция GetMaxMode. Возвращает значение типа Integer, содержащее количество возможных режимов работы
адаптера. Заголовок:
Function GetMaxMode: Integer;
Функция GetModeName. Возвращает значение типа String, содержащее разрешение экрана и имя режима работы
адаптера по его номеру. Заголовок:
Function GetModName(ModNumber: Integer): String;
Здесь ModNumber - номер режима.
Следующая программа после инициации
графического режима выводит на экран строку, содержащую имя загруженного
драйвера, а также все возможные режимы его работы.
Uses Graph;
Var a,b:
Integer;
begin
a:= Detect;
InitGraph(a, b, '');
WriteLn(GetDriverName);
for а:= 0 to GetMaxMode do WriteLn(GetModeName(a):10);
ReadLn;
CloseGraph; end.
3. Координаты, окна, страницы
Многие графические
процедуры и функции используют указатель текущей позиции на экране, который в
отличие от текстового курсора невидим. Положение этого указателя, как и вообще
любая координата на графическом экране, задается относительно левого верхнего
угла, который, в свою очередь, имеет координаты 0,0. Таким образом,
горизонтальная координата экрана увеличивается слева направо, а вертикальная -
сверху вниз.
Функции GetMaxX и
GetMaxY. Возвращают значения типа Word, содержащие максимальные координаты экрана в текущем
режиме работы соответственно по горизонтали и вертикали. Например:
Uses Graph;
Var a,b: Integer;
begin
a := Detect;
InitGraph(a, b, '');
WriteLn(GetMaxX,
GetMaxY:5);
ReadLn;ClogeGraph end.
Функции GetX и GetY.
Возвращают значения типа Integer, содержащие
текущие координаты указателя соответственно по горизонтали и вертикали.
Координаты определяются относительно левого верхнего угла окна или, если окно
не установлено, экрана.
Процедура SetViewPort.
Устанавливает прямоугольное окно на графическом экране. Заголовок:
Procedure SetViewPort(Xl,Yl,X2,Y2: Integer; ClipOn: Boolean);
Здесь Xl...Y2 - координаты левого верхнего (X1,Y1) и правого нижнего (X2,Y2) углов окна; ClipOn - выражение тип
Вооlean, определяющее
«отсечку» не умещающихся в окне элементов изображения.
Координаты окна всегда задаются
относительно левого верхнего угла экрана. Если параметр ClipOn имеет значение True, элементы
изображения, не умещающиеся в пределах окна, отсекаются, в противном случае
границы окна игнорируются. Для управления этим параметром можно использовать
такие определенные в модуле константы:
const
ClipOn = True; {Включить отсечку}
ClipOff = False; {He включать отсечку}
Следующий пример иллюстрирует действие
параметра ClipOn. Программа
строит два прямоугольных окна с разными значениями параметра и выводит в них
несколько окружностей. Для большей наглядности окна обводятся рамками (см. рис.1).
Puc..1. Отсечка изображения в окне
Uses Graph,CRT;
Var x,y,e: Integer;
xll,yll,xl2,yl2, {Координаты 1-го окна}
x21,x22, {Левый верхний угол 2-ro}
R, {Начальный радиус}
k: Integer;
begin
DirectVideo := False;{Блокируем прямой доступ к видеопамяти в модуле CRT} {Инициируем
графический режим}
x := Detect; InitGraph(x, у, ''); {Проверяем результат}
e := GraphResult; if e <> grOk then
WriteLn(GraphErrorMsg(e)) {Ошибка}
else
begin {Нет ошибки}
{Вычисляем координаты с учетом
разрешения экрана}
Xll:=GetMaxX div 60;
xl2:=GetMaxX div 3;
yll:= GetMaxY div 4;
yl2:= 2*yll;
R:=(Xl2-Xll) div 4;
x21:= Xl2*2;
x22:=x21+xl2-Xll;
{Рисуем
окна}
WriteLn('ClipOn:':10,'ClipOff:':40);
Rectangle(xll, yll,
xl2, yl2);
Rectangle(x21, yll,
x22, yl2) {Назначаем 1-е окно
и рисуем четыре окружности} SetViewPort(xll, yll, xl2, yl2, ClipOn);
for к. := 1 to 4 do
Circle(0,yll,R*k);
{Назначаем
2-е окно и рисуем окружности}
SetViewPort(x21, yll, x22, yl2, ClipOff);
for к := 1 to 4 do
Circle(0,yll,R*k);
{Ждем нажатия любой клавиши}
if ReadKey=#0 then к :=ord(ReadKey);
CloseGraph
end
end.
Процедура GetViewSettings.
Возвращает координаты и признак отсечки текущего графического окна. Заголовок:
Procedure GetViewSettings(var ViewInfo: ViewPortType);
Здесь ViewInfo - переменная
типа ViewPoriType. Этот тип в модуле Graph определен следующим образом:
type
ViewPortType = record
xl,yl,x2,y2: Integer; {Координаты окна} Clip : Boolean {Признак отсечки}
end;
Процедура MoveTo.
Устанавливает новое текущее положение указателя. Заголовок:
Procedure MoveTo(X,Y.- Integer);
Здесь X, Y - новые координаты указателя соответственно по
горизонтали и вертикали.
Координаты
определяются относительно левого верхнего угла окна или, если окно не установлено,
экрана.
Процедура MoveRel.
Устанавливает новое положение указателя в относительных координатах.
Procedure MoveRel(DX,DY: Integer);
Здесь DX,DY -приращение новых координат указателя соответственно по горизонтали
и вертикали.
Приращения задаются
относительно того положения, которое занимал указатель E моменту
обращения к процедуре.
Процедура ClearDevice.
Очищает графический экран. После обращения к процедуре указатель
устанавливается в левый верхний угол экрана, а сам экран заполняется цветом фона,
заданным процедурой SetBkColor. Заголовок:
Procedure ClearDevice;
Процедура ClearViewPort.
Очищает графическое окно, а если окно не определено к этому моменту - весь
экран. При очистке окно заполняется цветом с номером 0 из текущей палитры.
Указатель перемещается в левый верхний угол окна. Заголовок:
Procedure ClearViewPort;
В следующей программе на экране
создается окно, которое затем заполняется случайными окружностями рис.2).
После нажатия на любую клавишу окно очищается. Для выхода из программы нажмите
Enter.
Uses CRT,Graph; var
xl,yl,x2,y2,Err: Integer;
begin
{Инициируем графический режим}
xl := Detect; InitGraph(xl,x2,'');
Err := GraphResult;
WriteLn(GraphErrorMsg(Err))
else
begin {Определяем координаты окна с учетом разрешения экрана}
xl := GetMaxX div 4;
yl := GetMaxY div 4;
x2 := 3*xl; y2 := 3*yl; {Создаем окно}
Rectangle(xl,yl,x2,y2);
SetViewPort(xl+l,yl+l,x2-l,y2-l,ClipOn);
{Заполняем
окно случайными окружностями}
repeat
Circle(Random(GetMaxX),Random(GetMaxX), Random(GetMaxX div 5))
until KeyPressed; {Очищаем окно и ждем нажатия Enter}
ClearViewPort;
OutTextXY(0,0,'Press
Enter...'); ReadLn; CloseGraph end
end.
4. Линии и точки
Процедура PutPixel.
Выводит заданным цветом точку по указанным координатам. Заголовок:
Procedure PutPixel(X,Y: Integer; Color: Word);
Здесь X, Y - координаты точки; Color - цвет точки.
Координаты задаются относительно левого
верхнего угла окнаили, если окно не установлено, относительно левого верхнего
угла экрана.
Следующая программа периодически
выводит на экран «звездное небо» и затем гасит его. Для выхода из программы
нажмите любую клавишу.
Uses CRT,
Graph;
type
PixelType = record x, у : Integer; end
;
const N
= 5000;
(Количество "звезд"}
var d,r,e,k: Integer;
xl,yl,x2,y2: Integer;
a: array [l..N] of PixelType; {Координаты}
begin
{Инициируем графику}
d :=
Detect; InitGraph(d, r, '');
e := GraphResult; if e<>grOk then
WriteLn(GraphErrorMsg(e)) else
begin
{Создаем окно в центре экрана}
xl :=
GetMaxX div 4;
yl := GetMaxY div 4;
x2 := 3*xl; y2 := 3*yl;
Rectangle(xl,yl,x2,y2);
SetViewPort(xl+l,yl+l,x2-l,y2-l,ClipOn);
{Создаем и запоминаем координаты всех "звезд"}
for
k := 1 to N do with a[k] do begin
x := Random(x2-xl); у := Random(y2-yl) end;
{Цикл
вывода}
repeat
for k
:= 1 to N do
with a[k] do {Зажигаем "звезду"}
PutPixel(x,y,white);
if not KeyPressed
then for k := N downto 1 do
with a[k] do {Гасим "звезду"}
PutPixel(x,y,black)
until KeyPressed;
while KeyPressed do k :=
ord(ReadKey);
CloseGraph end ;
end.
Функция GetPixel. Возвращает значение типа Word, содержащее цвет пикселя с указанными координатами.
Заголовок:
Function GetPixel(X,Y: Integer): Word;
Здесь Х, Y - координаты пикселя.
Процедура Line. Вычерчивает линию с указанными координатами
начала и конца. Заголовок:
Procedure Line(Xl,Yl,X2,Y2: Integer);
ЗдесьХ1...Y1 - координаты начала (X1, Yl) и
конца(Xi2, Y2) линии.
Линия вычерчивается текущим стилем и
текущим цветом. В следующей программе в центре экрана создается окно, которое
затем расчерчивается случайными линиями. Для выхода из программы нажмите любую
клавишу.
Uses CRT, Graph;
Var d,r,e :
Integer,-xl,yl,x2,y2: Integer;
begin
{Инициируем графику}
d := Detect; InitGraph(d, r, ''); e := GraphResult;
if e <>
grOk then
WriteLn(GraphErrorMsg(e))
else
begin
{Создаем окно в центре экрана}
xl := GetMaxX div 4;
yl := GetMaxY div 4;
x2 := 3*xl; y2 :=
3*yl;
Rectangle(xl,yl,x2,y2);
SetViewPort(xl+l,yl+l,x2-l,y2-l,ClipOn);
{Цикл вывода случайных линий}
Repeat
SetColor(succ(Random(16)));
{Случайный цвет} Line(Random(x2-xl), Random(y2-yl), Random(x2-xl), Random(y2-yl)) until
KeyPressed;
if ReadKey=#0 then
d := ord(ReadKey);
CloseGraph end
end.
Процедура LineTo. Вычерчивает линию от текущего положения указателя
до по-дожения, заданного его новыми координатами. Заголовок:
Procedure LineTo(X,Y: Integer);
Здесь X, Y - координаты нового положения указателя, они же -
координаты второго конца линии.
Процедура LineRel. Вычерчивает линию от текущего положения указателя
до положения, заданного приращениями его координат. Заголовок:
Procedure LineRel (DX, DY: Integer);
Здесь DX, DY - приращения координат нового положения указателя.
В процедурах LineTo и LineRel линия вычерчивается текущим стилем и текущим
цветом.
Процедура SetLineStyle. Устанавливает новый стиль вычерчиваемых линий.
Заголовок:
Procedure SetLineStyle(Type,Pattern,Thick: Word)
Здесь Type, Pattern, Thick - соответственно тип, образец и толщина линии. Тип
линии может быть задан с помощью одной из следующих констант:
const
SolidLn = 0; {Сплошная линия}
DottedLn = 1; {Точечная линия}
CenterLn = 2; {Штрих-пунктирная
линия}
DashedLn = 3; {Пунктирная линия}
UserBitLn = 4; {Узор линии определяет
пользователь}
Параметр Pattern учитывается только для линий, вид которых
определяется пользователем (т.е. в случае, когда Type = UserBitLn). При этом два байта параметра Pattern определяют образец линии: каждый установленный в
единицу бит этого слова соответствует светящемуся пикселю в линии, нулевой бит
- несветящемуся пикселю. Таким образом, параметр Pattern задает отрезок линии длиной в 16 пикселей. Этот
образец периодически повторяется по всей длине линии.
Параметр Thick может принимать одно из двух значений:
const
NormWidth = 1; {Толщина в
один пиксель}
ThickWidth = 3; {Толщина в три
пикселя}
Процедура GetLineSettings.
Возвращает текущий стиль линий. Заголовок:
Procedure GetLineSettings(var Stylelnfo: LineSettingsType)
Здесь Stylelnfo - переменная типа LineSettingsType, в
которой возвращается текущий стиль линий.
Тип LineSettingsType определен в
модуле Graph
следующим образом:
type
LineSettingsType = record
LineStyle: Word; {Тип линии}
Pattern -. Word; {Образец}
Thickness: Word {Толщина} end;
Процедура SetWriteMode.
Устанавливает способ взаимодействия вновь выводимых линий с уже существующим
на экране изображением. Заголовок:
Procedure SetWriteMode(Mode);
Здесь Mode - выражение типа Integer, задающее
способ взаимодействия выводимых линий с изображением.
Если параметр Mode имеет значение 0, выводимые линии накладываются на
существующее изображение обычным образом (инструкцией MOV центрального процессора). Если значение 1, то это
наложение осуществляется с применением логической операции XOR (исключительное ИЛИ): в точках пересечения
выводимой линии с имеющимся на экране изображением светимость пикселей
инвертируется на обратную, так что два следующих друг за другом вывода одной и
той же линии на экран не изменяет его вид.
Режим,
установленный процедурой SetWriteMode, распространяется
на процедуры Drawpoly, Line, LineRel, LineTo и Rectangle. Для задания параметра Mode можно ис-юльзовать следующие определенные в модуле
константы:
const
CopyPut
= 0; {Наложение операцией MOV}
XORPut
= 1; {Наложение операцией XOR}
В следующем примере на
экране имитируется вид часового циферблата (рис. 14.3). Для наглядной
демонстрации темп хода «часов» ускорен в 600 раз (см. оператор Delау (100)). При
желании Вы сможете легко усложнить программу, связав ее показания с системными
часами и добавив секундную стрелку. Для выхода из программы нажмите на любую
клавишу.
Uses Graph, CRT;
Var d, r,
rl,r2,rr,k,Xl,yl,x2,y2,x01,y01: Integer,
Xasp,Yasp : Word;
begin
{Инициируем графику}
d:= detect;
InitGraph(d, r, '');
k:= GraphResult;
if k <> grOK then
WriteLn(GraphErrorMSG(к))
else
begin
{Определяем отношение сторон и размеры экрана}
xl:= GetMaxX div 2;
yl:= GetMaxY div 2;
GetAspectRatio(Xasp,
Yasp);
{Вычисляем радиусы:}
r:=round(3*GetMaxY*Yasp/8/Xasp);
rl:=round(0.9*r);{Часовые деления}
r2:=round(0.95*г); {Минутные деления}
{Изображаем циферблат}
Circle(xl,yl,г); {Первая
внешняя окружность} Circle(xl,yl,round(1.02*г));
{Вторая окружность}
for к := 0 to 59 do {Деления циферблата}
begin
if к mod 5=0 then
rr:=rl {Часовые деления}
else
rr:=r2; {Минутные
деления}
{Определяем координаты концов
делений}
х01:= xl+Round(rr*sin(2*pi*k/60));
у01:=
yl-Round(rr*Xasp*cos(2*pi*k/60)/Yasp);
x2 :=
xl+Round(r*sin(2*pi*k/60)) ;
y2 :=
yl-Round(r*Xasp*cos(2*pi*k/60)/Yasp);
Line(x01,y01,x2,y2) (Выводим деление} end;
{Готовим вывод стрелок}
SetWriteMode(XORPut);
SetLineStyle(SolidLn,0,ThickWidth);
r := 0;
{Счетчик минут в одном часе}
{Цикл вывода стрелок}
repeat
for к := 0 to 59 do {k = минуты}
if not KeyPressed then begin
{Координаты часовой стрелки}
x2 :=
xl+Round(0.85*rl*sin(2*pi*r/60/12));
y2 := yl-Round(0.85*rl*Xasp*COs(2*pi*r/60/12)/Yasp);
{Координаты минутной стрелки}
х01 := xl+Round(r2*sin(2*pi*k/60));
yOl :=
yl-Round(r2*Xasp*cos(2*pi*k/60)/Yasp);
{Изображаем стрелки}
Line(xl,yl,x2,y2);
Line(xl,yl,x01,y01);
Delay(100); {Для
имитации реального темпа
нужно установить задержку 60000}
{Для удаления стрелок выводим их еще
раз!}
Line(xl,yl,х01,yOl);
Line(xl,yl,x2,y2) ;{Наращиваем
и корректируем счетчик минут в часе};
Inc(r);
if r=12*60 then
r := О
end
until KeyPressed;
if ReadKey=#0 then k:=ord(ReadKey)
;
CloseGraph end
end.
5. Многоугольники
Процедура Rectangle. Вычерчивает
прямоугольник с указанными координатами углов. Заголовок:
Procedure Rectangle(XI,Yl,Х2,Y2: Integer);
Здесь X1...Y2 - координаты левого верхнего (XI, Y1) и правого нижнего (Х2, Y2) углов прямоугольника. Прямоугольник вычерчивается с
использованием текущего цвета и текущего стиля линий.
В следующем примере на экране
вычерчиваются 10 вложенных друг в друга прямоугольников.
Uses Graph, CRT;
Var d,r,e,xl,yl,x2,y2,dx,dy:
Integer;
begin
{Инициируем графику}
d := Detect; InitGraph(d, r, '');
e := GraphResult;
if e <> grOK then
WriteLn(GraphErrorMsg(e))
else
begin
{Определяем приращения сторон}
dx := GetMaxX div 20;
dy := GetMaxY div 20;
{Чертим вложенные прямоугольники}
for d := 0 to 9 do
Rectangle(d*dx,d*dy,GetMaxX-d*dx,GetMaxY-d*dy);
if ReadKey=#0
then d:=ord(ReadKey);
CloseGraph end j
end.
Процедура DrawPoly. Вычерчивает произвольную ломаную линию,
заданную координатами точек излома.
Procedure DrawPoly(N:
Word; var Points)
Здесь N - количество
точек излома, включая обе крайние точки; Points - переменная
типа PointType, содержащая координаты точек излома.
Координаты точек
излома задаются парой значений типа Word: первое
определяет горизонтальную, второе - вертикальную координаты. Для них можно
использовать следующий определенный в модуле тип:
type
PointType
= record
x,y:word
end;
При вычерчивании
используется текущий цвет и текущий стиль линий. Вот как, например, можно с
помощью этой процедуры вывести на экран график синуса:
Uses Graph;
Const N = 100;
(Количество точек графика}
Var d, r, e:
Integer;
m:array
[0..N+1] of PointType;
k :
Word;
begin
{Инициируем графику} d := Detect; InitGraph(d, r, '');
e :=
GraphResult;
if
e <> grOk then,
WriteLn(GraphErrorMsg(e))
else
begin
{Вычисляем координаты графика}
for
k := 0 to N do with m[k] do begin
x :=
trunc(k*GetMaxX/N);
у := trunc(GetMaxY*(-sin(2*Pi*k/N)+l)/2) end;
{Замыкаем график прямой линией}
m[succ(N)].x
:= m[0] .x;
m[succ(n)].y
:= m[0] .у;
DrawPoly(N
+ 2, m); ReadLn; CloseGraph
end
end.
В этом примере для
проведения горизонтальной прямой используется «замыкание» ломаной - первая и
последняя координаты ее точек излома совпадают.
Замечу, что хотя
количество точек излома N - выражение типа Word, на самом деле внутри процедуры на этот
параметр накладываются ограничения, связанные с конечным размером используемой
буферной памяти. Вы можете убедиться в этом с помощью, например, изменения N
в предыдущем примере: при N==678 график перестанет выводиться
на экран, а функция GraphResult будет возвращать значение -6 (не хватает
памяти для просмотра областей). Таким образом, для этой программы пороговое значение
количества точек излома составляет 679.
6. Дуги, окружности, эллипсы
Процедура Circle.
Вычерчивает окружность. Заголовок:
Procedure Circle(X,Y: Integer; R: Word);
Здесь X, Y- координаты
центра; R - радиус в
пикселях.
Окружность выводится текущим цветом. Толщина линии
устанавливается текущим стилем, вид линии всегда SolidLn (сплошная). Процедура вычерчивает правильную
окружность с учетом изменения линейного размера радиуса в зависимости от его направления
относительно сторон графического экрана, т.е. с учетом коэффициента GetAspectRatio. В связи с этим параметр R определяет количество пикселей в горизонтальном
направлении.
В следующем
примере в центре экрана создается окно, постепенно заполняющееся случайными
окружностями. Для выхода из программы нажмите на любую клавишу.
Uses Graph, CRT;
Var d,r,e,x,y:
Integer;
begin
{Инициируем графику}
d := Detect;
InitGraph(d, r, ' ')
;
e := GraphResult;
if e <> grOK then
WriteLn(GraphErrorMsg(e))
else begin
{Создаем окно
в центре экрана}
х := GetMaxX div 4;
у := GetMaxY div 4;
Rectangle(x,у,3*х,3*у);
SetViewPort(x+l,y+l,3*x-l,3*y-l,ClipOn);
{Цикл вывода случайных окружностей}
repeat
SetColor(succ(Random(white))); {Случайный цвет}
SetLineStyle(0,0,2*Random(2)+1); {и стиль
линии}
x := Random(GetMaxX); {Случайное
положение}
у := Random(GetMaxY); {центра
окружности}
Circle(x,у,Random(GetMaxY div 4)); until
KeyPressed;
if ReadKey=#0 then x := ord(ReadKey);
CloseGraph
end
end.
Процедура Arc. Чертит
дугу окружности. Заголовок:
Procedure Arc(X,Y: Integer; BegA,EndA,R:
Word);
Здесь X, Y - координаты центра; BegA, EndA - соответственно начальный и конечный углы дуги;
R - радиус.
Углы отсчитываются
против часовой стрелки и указываются в градусах. Нулевой угол соответствует
горизонтальному направлению вектора слева направо. Если задать значения
начального угла 0 и конечного - 359, то будет выведена полная окружность. При
вычерчивании дуги окружности используются те же соглашения относительно линий и
радиуса, что и в процедуре Circle.
Вот как выглядят две дуги: одна с
углами 0 и 90, вторая 270 и 540 градусов (рис. 14.6):
Процедура Ellipse.
Вычерчивает эллипсную дугу. Заголовок:
Procedure Ellipse(X,Y: Integer; BegA,EndA,RX,RY: Word);
Здесь X, Y - координаты центра; BegA, EndA - соответственно начальный и конечный: углы дуги; RX, RY- горизонтальный и вертикальный радиусы эллипса в
пикселях.
При вычерчивании дуги эллипса
используются те же соглашения относительно лв-ний, что и в процедуре Circle, и те же соглашения относительно углов, что и в
процедуре Arc. Если радиусы
согласовать с учетом масштабного коэффициента GetAspectRatio, будет вычерчена правильная окружность.
В следующей программе вычерчиваются три
эллипсных дуги (рис. 14.7) при разных отношениях радиусов. Замечу, что чем выше
разрешение графического экрана, тем ближе к единице отношение сторон и тем
меньше первый график отличается от третьего.
Uses Graph, CRT;
Var d,r,e: Integer; xa,ya: Word;
begin
{Инициируем графику} d := Detect;
InitGraph(d, r, ' ')
;
e := GraphResult; if
e <> grOK then
WriteLn(GraphErrorMsg(e))
else begin
{Первый график}
OutTextXY(50,40,'RX =
RY'); {Надпись}
Line
(0,100,160,100); {Ось X}
Line (80,55,80,145); {Ось У}
Ellipse
(80,100,180,90,40,40);
{Второй график}
OutTextXY(260,40,'RX = 5*RY');
Line
(190,100,410,100);
Line (300,55,300,145);
Ellipse
(300,100,0,359,100,20);
{Третий график}
OutTextXY(465,40,'Aspect
Ratio');
Line
(440,100,600,100);
Line
(520,55,520,145);
GetAspectRatio(xa, ya) ;
Ellipse (520,100,0,270,40,round(40*(xa/ya)));
if ReadKey=#0 then d := ord(ReadKey);
CloseGraph end end.
7. Краски, палитры, заполнения
Процедура SetColor.
Устанавливает текущий цвет для выводимых линий и символов. Заголовок:
Procedure SetColor(Color: Word);
Здесь Color - текущий цвет.
В модуле Graph определены точно такие же константы для задания
цвета, как и в модуле CRT .
Функция GetColor.
Возвращает значение типа Word, содержащее
код текущего цвета. Заголовок:
Function GetColor:
Word;
Функция GetMaxColor.
Возвращает значение типа Word, содержащее
максимальный доступный код цвета, который можно использовать для обращения к SetColor. Заголовок:
Function GetMaxColor: Word;
Процедура SetBkColor.
Устанавливает цвет фона. Заголовок: Procedure SetBkColor(Color: Word);
Здесь Color - цвет фона.
В отличие от текстового
режима, в котором цвет фона может быть только темного оттенка, в графическом
режиме он может быть любым. Установка нового цвета фона немедленно изменяет
цвет графического экрана. Это означает, что нельзя создать изображение, два
участка которого имели бы разный цвет фона. Для CGA-адаптера в режиме высокого разрешения установка
цвета фона изменяет цвет активных пикселей. Замечу, что после замены Цвета фона
на любой, отличный от 0 (Black) цвет,
Вы не сможете более использовать цвет 0 как черный, он будет заменяться на цвет
фона, т.к. процедуры модуля Graph интерпретируют
цвет с номером 0 как цвет фона. Это означает, в частности, что Вы уже не
сможете вернуть фону черный цвет!
Если Ваш ПК оснащен
цветным экраном, следующая программа продемонстрирует работу процедуры SetBkColor. Программа выводит десять вложенных друг в друга
прямоугольников, после чего циклически меняет цвет фона. Для выхода из
программы достаточно нажать на любую клавишу.
Uses Graph, CRT;
Const NC: array [0..15] of String [12] =
('Black','Blue','Green','Cyan','Red','Magenta',
'Brown','LightGray','DarkGray','LightBlue',
'LightGreen','LightCyan','LightRed', 1LightMagenta','Yellow','White');
var
d, r, e, k, color,
dx, dy: Integer;
begin
{Инициируем графику}
d := Detect; InitGraph(d, r, ");
e := GraphResult;
if e <> grOK then
WriteLn(GraphErrorMsg(e))
else
begin
{Выводим текст в центре экрана}
OutTextXY(200,GetMaxY
div 2,'BACKGROUND COLOR’);
dx -:= GetMaxX div
30; {Приращение длины}
dy := GetMaxY div 25; {Приращение высоты}
for k := 0 to 9 do {Выводим 10 прямоугольников}
Rectangle(k*dx,k*dy,GetMaxX-k*dx,GetMaxY-k*dy);
color :=
black; (Начальный цвет
фона}
repeat {Цикл смены фона}
SetBkColor(color);
SetFillStyle(0,Color);
Bar(345,GetMaxY div
2,440,GetMaxY div 2+8);
OutTextXY(345,GetMaxY
div 2,NC[color]);
inc(color);
if color > White then color :=
Black until KeyPressed;
if ReadKey=#0 then к :=
ord(ReadKey); CloseGraph end end.
Функция GetBkColor.
Возвращает значение типа Word, содержащее
текущий цвет фона. Заголовок:
Function GetBkColor: Word;
Процедура SetPalette.
Заменяет один из цветов палитры на новый цвет. Заголовок:
Procedure SetPalette(N: Word; Color: ShortInt);
Здесь N- номер цвета в палитре; Color - номер вновь устанавливаемого цвета.
Данная процедура может
работать только с адаптерами EGA или VGA. Она не должна использоваться с IBM8514 или 256-цветным вариантом VGA - для этих адаптеров предназначена особая процедура SetRGBPalette (см. ниже). Первоначальное размещение цветов в
палитрах EGA/VGA соответствует
последовательности их описания константами Black,...,White, т.е.
цвет с индексом 0 - черный, 1 - синий, 2 - зеленый и т.д. После обращения к
процедуре все фрагменты изображения, выполненные цветом с индексом N из
палитры цветов, получат цвет Color. Например,
если выполнить оператор
SetPalette(2,White) ;
то цвет с индексом 2
(первоначально это - бирюзовый цвет Cyan) будет
заменен на белый. Замечу, что цвет с индексом 0 отождествляется с цветом фона и
может изменяться наряду с любым другим цветом.
Функция GetPaletteSize.
Возвращает значение типа Integer, содержащее
размер палитры (максимальное количество доступных цветов). Заголовок:
Function GetPaletteSize: Integer;
Процедура GetDefaultPalette. Возвращает структуру палитры, устанавливаемую по умолчанию (в режиме
автонастройки). Заголовок:
Procedure GetDefaultPalette(var Palette: PaletteType);
Здесь Palette - переменная типа PaletteType (см.
процедуру GetPalette), в которой
возвращаются размер и цвета палитры.
Процедура SetFillStyle.
Устанавливает стиль (тип и цвет) заполнения. Заголовок:
Procedure SetFillStyle(Fill,Color: Word);
Здесь Fill - тип заполнения; Color - цвет
заполнения.
С помощью
заполнения можно покрывать какие-либо фрагменты изображения периодически
повторяющимся узором. Для указания типа заполнения используются следующие
предварительно определенные константы:
const
EmptyFill
|
= 0
|
{Заполнение фоном (узор отсутствует)}
|
SolidFill
|
= 1
|
{Сплошное заполнение}
|
LineFill
|
= 2
|
{Заполнение------}
|
LtSlashFill
|
= 3
|
{Заполнение ///////}
|
SlashFill
|
= 4
|
{Заполнение
утолщенными ///}
|
BkSlashFill
|
= 5
|
{Заполнение
утолщенными \\\}
|
LtBkSlashFill
|
= 6
|
{Заполнение
\\\\\\\}
|
HatchFill
|
= 7
|
(Заполнение
+++++++}
|
XHatchFill
|
= 8
|
(Заполнение
ххххххх}
|
InterleaveFill
|
= 9
|
(Заполнение
прямоугольную клеточку}
|
WideDotFill
|
= 10
|
{Заполнение
редкими точками}
|
CloseDotFill
|
= 11
|
{Заполнение
частыми точками}
|
UserFill
|
= 12
|
(Узор определяется пользователем}
|
Процедура FloodFill.
Заполняет произвольную замкнутую фигуру, используя текущий стиль заполнения
(узор и цвет). Заголовок:
Procedure FloodFill(X,Y: Integer; Border: Word);
Здесь X, Y- координаты любой точки внутри замкнутой фигуры; Border - цвет граничной линии.
Если фигура незамкнута, заполнение
«разольется» по всему экрану.
Следует учесть, что реализованный в
процедуре алгоритм просмотра границ замкнутой фигуры не отличается
совершенством. В частности, если выводятся подряд две пустые строки, заполнение
прекращается. Такая ситуация обычно возникает при заполнении небольших фигур с
использованием типа LtSlashFill. В
фирменном руководстве по Турбо Паскалю рекомендуется, по возможности, вместо
процедуры FloodFill использовать FillPoly (заполнение прямоугольника).
Процедура Bar. Заполняет
прямоугольную область экрана. Заголовок:
Procedure
Bar(XI,Y1,X2,Y2:
Integer);
Здесь X1...Y2 - координаты левого верхнего (XI, Y1) и правого нижнего (Х2, Y2) углов закрашиваемой области.
т
Процедура закрашивает (но не обводит)
прямоугольник текущим образцом узора и текущим цветом, которые устанавливаются
процедурой SetFillStyle.
Следующая программа дает красивые
цветовые эффекты (закраска случайных прямоугольников).
Uses Graph, CRT; var d, г, е : Integer;
begin
{Инициируем графику} d := Detect; InitGraph(d, r, '');
e := GraphResult;
if e <> grOk then
WriteLn(GraphErrorMsg(e))
else begin
{Создаем окно в центре экран}
d := GetMaxX div 4;
r := GetMaxY div 4;
Rectangle(d,r,3*d,3*r);
SetViewPort(d+1,r+1,3*d-l,3*r-l,ClipOn);
{Цикл вывода и закраски случайных
многоугольников}
repeat
SetFillStyle(Random(12),Random(succ(GetMaxColor)));
Bar(Random(GetMaxX),Random(GetMaxY),
Random(GetMaxX),Random(GetMaxY));
until
KeyPressed;
if ReadKey=#0 then d := ord(ReadKey);
CloseGraph
end end.
Процедура ВагЗР.
Вычерчивает трехмерное изображение параллелепипеда и закрашивает его переднюю
грань . Заголовок:
Procedure Bar3D (XI,Y1,X2,Y2,Depth: Integer; Top: Boolean);
8. Примеры
Нарисовать
эмблемы фирм: 1) LG; 2) SONY; 3) PHILIPS; 4) SAMSUNG (рис.1-4,).
Эмблемы известных фирм
содержат много любопытной информации. Так два года шла работа над проектом
новой эмблемы группы "Samsung". Её динамичный дизайн соответствует облику
успешно прогрессирующего и растущего предприятия. Голубой цвет означает
стабильность и надёжность. Эллипс символизирует движение мира через космос,
несёт в себе идею постоянного изменения и обновления. Первая и последняя буквы
в слове Samsung слегка выступают за рамку овала, что отражает связь внутреннего
и внешнего, показывает стремление фирмы быть единым со всем миром и служить
обществу как единому целому.
Изучая эмблемы как геометрические
объекты, можно найти немало интересного и в моделировании их на дисплее.
Рассмотрим некоторые эмблемы в качестве упражнений по расчёту экранных
координат.
1)
Uses Crt,Graph;
Var Gd,Gm,x,y: Integer;
BEGIN Gd:=Vga; Gm:=VgaHi;
InitGraph(Gd,Gm,■'); SetColor(Red); SetFillStyle(1,Red);
FillEllipse(225,240,160,160); {большой красный круг}
SetColor(White); SetFillStyle(1,White);
FillEllipse(175,180,20,20); {внутренний белый кружок}
Bar(220,160,235,320);
Bar(230,320,265,305);
{буква L}
Arc(225,240,90,360,125);
{дуга 1}
Arc(225,240,90,360,140);
{дуга 2}
Line(225,100,225,115); {черта,соединяющая дуги)
Bar(265,235,365,250); {черта в букве G справа)
FloodFill(220,110,White); {
заливка буквы G}
{ надпись }
SetColor(LightGray); SetTextStyle(3,0,1);
SetUserCharSize(4,l,4,l); for x:=420 to 430 do
for y:=150 to 160 do
OutTextXY(x,y,’LG’); {
смена цвета фона }
ReadLn; SetBkColor(LightRed);
ReadLn; SetBkColor(White);
ReadLn; CloseGraph
END.
Arc(x,y. Integer, StartAngle, EndAngle, r:
Word) - процедура рисования дуги радиуса г из центра с координатами (х,у). StartAngle и EndAngle
-градусные меры начала и конца дуги. Для заливки замкнутого контура
(изображения буквы G) можно использовать универсальную процедуру FloodFill(x,y: Integer, Border: Word). Она
заливает область вокруг точки (х,у), ограниченную линиями цвета Border.
2)
Uses Crt,Graph;
Const r: Byte=10;
draw: Boolean=true;
Var Gd,Gm,x,y,columns,row: Integer;
BEGIN Gd:=Vga; Gm:=VgaHi;
InitGraph(Gd,Gm,’’);
SetBkColor(LightGray); SetColor(Blue);
SetFillStyle(1,Blue);
for columns:=1 to 7 do begin
for row:=l to 7 do begin
if columns>5 then Case columns of
6: draw:=Not(row in [2,3] );
7: draw:=Not(row in [1..4.7]);
end;
if draw then
FillEllipse(170+columns*35,60+row*35,r,r) end;
if columns in [1,3,5] then Inc(r,2) end;
SetTextStyle(l,0,l);
SetUserCharSize(3,1,2,1) ;
for x:=200 to 203 do
for y:=320 to 323 do
OutTextXY(x,y,"SONY1); ReadLn; SetBkColor (White) ;
ReadLn,SetPalette(l,5) ;
SetBkColor(Cyan); ReadLn; CloseGraph
END.
Приведенная программа содержит
вложенные циклы, параметры которых используются при расчёте координат центров
кругов.
3)
Uses Crt,Graph;
Var Gd,Gm,x,y,y0,i,k: Integer;
BEGIN Gd:=Vga; Gm:=VgaHi;
InitGraph(Gd,Gm,■');
SetBkColor(Blue); SetColor(White);
for k:=0 to 1 do begin
{ внешний контур }
Line(220+k,90,220+k,250);
Line(420-k,90,420-k,250);
Line(220,90-k,420,90-k);
Arc(320,250,180,360,100-k);
Circle(320,250,90+k); { внутренний круг }
for i:=l to 3 do
{ 3 синусоиды }
for x:=230 to 410 do PutPixel(x,232+Round(6*Sin(x/15-6))+i*10+k,15);
{ 2 большие звезды }
Х:=270+к*100; у:=205+к*90; MoveTo(х,у-30);
LineTo(x+2,y-2); LineTo(х+30,у);
LineTo(x+2,y+2); LineTo(x,y+30);
LineTo(x-2,y+2); LineTo(x-30,у) ;
LineTo(х-2,у-2);
LineTo(x,y-30);
FloodFill(x,y,White);
{ 2 меньшие звезды }
x:=290+k*60; y:=185+k*130; MoveTo(x,y-20);
LineTo(x+l,y-l); LineTo(x+20,у);
LineTo(x+l,y+l); LineTo(x,y+20);
LineTo(x-l,y+l); LineTo(x-20,y);
LineTo (x-l,y-l) ; LineTo(x,y-20);
FloodFill(x,y,White) end; {for}
SetFillStylefl,White); SetTextStyle(6,0,4);
for x:=238 to 243 do
for y:=100 to 102 do OutTextXY(x,y,'P H I L
I P S'); ReadLn; SetBkColor(Cyan); ReadLn; SetBkColor(Red); ReadLn; CloseGraph
END.
Параметр цикла к в
программе используется для рисования пар без применения процедур, а также
двойных линий.
4)
Uses Crt,Graph;
Const xl=160; yl=270; x2=480; y2=214;
Var Gd,Gm : Integer; x,y,a,b: Longlnt;
BEGIN Qd:=Vga; Om:=VgaHi;
InitGraph(Gd,Gm,' ') ;
for x:=150 to 495 do begin
a:=Sgr(x-xl); b:=Sqr(x-x2); for y:=180 to
300 do ^f Sqrt(a+Sqr(y-y1))+
Sqrt(b+Sqr(y-y2))<334 then
PutPixel(x,y,1)
{ else PutPixel (x,y,7) } end;
SetColor(White); SetTextStyle (3,0,1);
SetUserCharSize(1,1,1,1) ; for x:=202 to 205 do for y:=220 to 223 do
OutTextXY(x,y, 'S A M S U N G');
ReadLn; SetBkColor(Cyan); ReadLn;
SetBkColor(Blue); SetPalette(Blue,White); SetPalette(White,Blue); ReadLn;
CloseGraph;
END.
ЗАКЛЮЧЕНИЕ
В данной курсовой работе описываются различные
процедуры и функции, предназначенные для создания графических объектов в Турбо
Паскале.
Используя выше перечисленные процедуры и функции, я
научился изображать различные фигуры различных форм и размеров, так же смог
показать движение фигуры.
Написав данные программу, я получил навык работы в
графической среде Турбо Паскаль, научился правильно применять разные процедуры
и функции, точно определять и задавать координаты различных линий, эллипсов,
окружностей, прямоугольников и т.д.
СПИСОК ИСПОЛЬЗОВАННОЙ ЛИТЕРАТУРЫ
1) Информатика(Базовый
курс) С. В. Симонович, СПб: Питер, 2001г.
2) Основы
языка Turbo Pascal(учебный курс), П. И. Рудаков, М. А.
Федотов, Москва: Радио и Связь, 2000г.
3) Основы
программирования в задачах и примерах, А. В. Милов, Харьков: ФОЛИО, 2002г.
4) Практикум
программирования на Turbo Pascal. Задачи, алгоритмы и решения.-2-е
изд.-СПб.:ООО»ДиаСофтЮп», 2002.
5) Практика
программирования, Ю. Кетков, А. Кетков, СПб: БХБ/ Петербург, 2002г.
6) Фаронов
В.В. Turbo Pascal 7.0 Начальный курс. Учебное пособие.-М: Издательство «ОМД
Групп», 2003.-616 с.:ил.
7)
Turbo Pascal: учитесь программировать, О.
А. Меженный, Москва: изд.дом «Вильямс», 2001г