МИНИСТЕРСТВО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ МОСКОВСКИЙ ГОСУДАРСТВЕННЫЙ ИНСТИТУТ РАДИОТЕХНИКИ, ЭЛЕКТРОНИКИ И АВТОМАТИКИ

advertisement
МИНИСТЕРСТВО ОБРАЗОВАНИЯ РОССИЙСКОЙ
ФЕДЕРАЦИИ
МОСКОВСКИЙ ГОСУДАРСТВЕННЫЙ ИНСТИТУТ
РАДИОТЕХНИКИ, ЭЛЕКТРОНИКИ И АВТОМАТИКИ
(ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ)
Факультет: Вычислительных машин и систем
КОМПЬЮТЕРНАЯ ГРАФИКА
Методические указания по выполнению
лабораторной работы №1
Тема: "Графические средства операционной
системы Windows"
Составитель: Чертков К.К.
Москва, 2005
2 ЦЕЛЬ РАБОТЫ: познакомиться с
возможностями подсистемы GDI операционной системы Windows и средствами, предоставляемыми
средой Delphi для работы с ней.
ЗАДАЧА: в соответствии с выбранным вариантом задания создать в среде Delphi программу,
формирующую изображение, построенное из графических примитивов, предоставляемых GDI:
линий, дуг, эллипсов, залитых областей и пр.
1. Основные события, используемые для управления интерактивной
графической программой
Взаимодействие прикладных программ с операционной системой Windows со стороны последней
организуется в виде отправки им сообщений. Как только в системе происходит какое-то событие,
имеющее отношение к данной программе, в ее очередь сообщений помещается соответствующее
сообщение. Например, при вводе символа с клавиатуры посылается сообщение с кодом WM_CHAR,
при нажатии левой кнопки мыши — WM_LBUTTONDOWN, при срабатывании таймера —
WM_TIMER. Благодаря существованию механизма сообщений несколько программ могут
одновременно использовать одни и те же системные ресурсы: клавиатуру, мышь, дисплей и пр. В
однозадачной операционной системе MS-DOS, например, запускавшаяся прикладная программа
единолично владела всеми ресурсами и освобождала их только при завершении.
Каждое приложение Windows с графическим интерфейсом (GUI - Graphics User Interface)
находится в постоянном ожидании прихода сообщений, проверяя в цикле свою очередь сообщений.
Когда новое сообщение извлекается из очереди, оно передается процедуре, ответственной за его
обработку. Например, при получении сообщения WM_CHAR тестовым редактором будет вызвана
процедура, которая вставит введенный символ в документ. После того, как обработчик закончит
свою работу, программа снова возвращается к циклу ожидания сообщений.
Всего существует более 900 различных сообщений, которые может получить программа. Но. к
счастью, программисту нет необходимости самому писать обработчик для каждого из них.
Программа может обрабатывать только те сообщения, которые имеют для нее смысл. Остальные
передаются обработчику сообщений по умолчанию, предоставляемому операционной системой. Он
выполняет всю необходимую работу.
3
В Delphi обработка сообщений скрыта в методе Run объекта Application, вызываемого при
запуске программы (смотрите файл проекта Delphi с расширением .dpr). Вместо этого разработчику
предоставляется гораздо более удобный механизм событий. Для Каждого визуального компонента
(форма, кнопка, строка редактирования и пр.) определен список событий, которые могут с ним
происходить (их можно увидеть на вкладке «События» («Events») Инспектора объектов (Object
Inspector). Название каждого события начинается с приставки «On» (OnPaint, OnClick и т.п.).
Когда программа, написанная на Delphi, получает, например, сообщение о том, что с клавиатуры
введен символ (сообщение WM_CHAR), то считается, что наступило событие OnKeyPress и
вызывается назначенный ему обработчик. Обработчик события — это стандартная процедура языка
Паскаль со строго определенным списком параметров. Каждому событию соответствует свой набор
параметров. Например, обработчик единичного перемещения курсора мыши над формой (событие
OnMouseMove) имеет параметры X и Y типа Integer, через которые передаются его новые
координаты, а обработчик ввода символа (OnKeyPress) — параметр Key типа Char, в который
помещается код введенного символа.
Создание и назначение обработчиков событий осуществляется в Инспекторе объектов. После
того, как обработчик создан, в него вручную добавляется код.
Ниже приводится краткое описание наиболее важных событий формы и приведены примеры
обработчиков некоторых из них.
Специфические типы параметров обработчиков событий
Тип
Описание
TMouseButton
type TMouseButton = (mbLeft, mbRight, mbMiddle);
Используется для передачи обработчикам событий от мыши информации о том, нажатие
какой кнопки вызвало данное событие. mbLeft означает левую кнопку, mbRight — правую, а
mbMiddle — среднюю.
TShiftState
type TShiftState = set offssShift, ssAlt, ssCtrl, ssLeft, ssRight, ssMiddle, ssDouble);
Используется для передачи обработчикам события от мыши и клавиатуры информации о
состоянии кнопок мыши и управляющих клавиш клавиатуры. Параметр данного типа
является множеством и содержит элемент ssShift, если при возникновении события была
нажата клавиша Shift, ssAlt — если клавиша Alt, ssCtrl — если клавиша Ctrl, ssLeft — если
левая кнопка мыши, ssRight — если правая кнопка мыши, ssMiddle — если средняя кнопка
мыши, ssDouble — если был двойной щелчок.
Типы событий
Тип
Описание
TNotifyEvent
type TNotifyEvent = procedure (Sender: TObject) of object;
Используется для событий, которые не требуют передачи параметров. Sender —
единственный параметр-ссылка на объект, являющийся источником события.
TMouseEvent
type TMouseEvent = procedure (Sender: TObject; Button: TMouseButton; Shift: TShiftState; X,
Y: Integer) of object;
Используется для создания обработчиков нажатия и отпускания кнопок мыши, когда
требуется знать, какие нажаты кнопки мыши, управляющие клавиши на клавиатуре (Ctrl,
Shift, Alt), какие координаты имеет курсор мыши (X, Y).
TMouseMoveEvent
type TMouseMoveEvent = procedure(Sender: TObject; Shift: TShiftState; X, Y: Integer) of object;
Тип обработчика перемещения курсора мыши. Ему передается список нажатых
управляющих клавиш на клавиатуре, список нажатых кнопок мыши и координаты курсора
мыши.
TKeyPressEvent
type TKeyPressEvent = procedure (Sender: TObject; var Key: Char) of object;
Тип обработчика нажатия символьной клавиши на клавиатуре.
TKeyEvent
TKeyEvent = procedure (Sender: TObject; var Key: Word; Shift: TShiftState) of object;
Тип обработчика нажатия или отпускания произвольной клавиши на клавиатуре.
Обработчик такого типа реагирует на нажатие символьных, функциональных и
управляющих клавиш, а также на нажатие комбинаций клавиш с Shift, Ctrl и Alt.
Краткие сведения о некоторых событиях формы (класс TForm)
Событие
Тип
Описание
OnClick
TNotifyEvent
Происходит при щелчке главной (обычно левой) кнопкой мыши в рабочей
OnDblClick
TNotifyEvent
OnMouseDown
TMouseEvent
области формы.
Происходит при двойном щелчке главной (обычно левой) кнопкой мыши в
рабочей области формы.
Происходит при нажатии любой кнопки мыши в рабочей области формы.
Позволяет отслеживать текущие координаты указателя мыши в окне.
OnMouseMove
TMouseMoveEvent
OnMouseUp
TMouseEvent
OnKeyPress
TKeyPressEvent
OnKeyDown
TKeyEvent
Параметр Key типа char содержит код введенный символа.
Происходит при нажатии произвольной клавиши на клавиатуре.
OnKeyUp
TKeyEvent
Происходит при отпускании произвольной клавиши на клавиатуре.
Происходит при перемещении курсора мыши в рабочей области
формы. Позволяет отслеживать его положение.
Происходит при отпускании кнопки мыши.
Происходит
при нажатии пользователем
символьной
клавиши.
OnResize
TNotifyEvent
Происходит при изменении размера формы. Может использоваться для
того, чтобы переформатировать находящуюся в окне информацию.
OnCreate
TNotifyEvent
OnPaint
TNotifyEvent
Происходит при создании формы.
Обычно
используется для
инициализации данных.
Происходит, когда изображение на форме должно быть перерисовано.
Перерисовывается только та область формы, которая помечена как
недействительная. Такая область на форме может появиться, например, в
результате ее перекрытия другим окном или же в результате
увеличения размера формы.
Примеры обработчиков некоторых событий
OnClick. Выводит окошко с надписью «Привет!» при щелчке левой кнопкой мыши в
рабочей области формы (рис. 1).
procedure TForml.FormClick(Sender: TObject);
begin
ShowMessage ( 'Привет! ');
end;
Рис. 1. Результат работы обработчика события OnClick
OnMouseDown. При нажатии кнопки мыши в рабочей области формы выводит ее название,
название нажатых управляющих клавиш (Ctrl, Alt и Shift) и координаты курсора мыши (рис. 2).
procedure TForml.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer); var
s: string;
begin
{Определим, какая нажата кнопка мыши}
case Button of
mbLeft: S := s + 'Нажата левая кнопка мыши. ';
mbRight: S := s + 'Нажата правая кнопка мыши. ';
mbMiddle: S := s + 'Нажата средняя кнопка мыши.';
6
end;
s := s + #13+#10;
{Определим, какие нажаты управляющие клавиши}
if ssShift in Shift then s := s + 'Нажата клавиша Shift. ';
if ssAlt in Shift then s := s + 'Нажата клавиша Alt. ';
if ssCtrl
in Shift then s := s + 'Нажата клавиша Ctrl.';
s := s + #13+#10;
{Определим координаты курсора}
s := s + 'Координаты курсора (х, у): ' + IntToStr(X) + ', ' + IntToStr(Y);
{Выведем сообщение в окошке}
ShowMessage(s);
Рис. 2. Результат вызова обработчика события OnMouseDown
OnKeyPr&ss. При нажатии клавиши "T"- показывает текущее время, при нажатии 'D' —
текущую дату (рис. 3).
procedure TForml.FormKeyPress(Sender: TObject; var Key: Char);
begin
if ((Key = 't') or (Key = "T" ) ) then
ShowMessage('Текущее время: ' + TimeToStr(Time()))
else if((Key = 'd') or (Key = 'D')) then
ShowMessage('Текущая дата: ' + DateToStr(Date()));
end;
_________________________________________________________________________________________________________________________________________________------------------
Рис. 3. Результат нажатия клавиши 'Т'
OnKeyDown. При нажатии стрелки вверх увеличивается яркость каждой из компонент
цвета формы на 5 единиц, при нажатии стрелки вниз — уменьшается. При нажатии клавиши
Escape при помощи стандартной функции MessageBox выводится окошко с вопросом о
завершении программы (рис. 4) и в случае, если пользователь нажимает кнопку Yes, форма
7
закрывается командой Close и программа завершается. При нажатии клавиши F1 выводится
справочное окошко (рис. 5).
procedure TForml.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
Определим, нажата ли одна из заданных клавиш}
case Key of
{при нажатии стрелки вверх увеличим яркость цвета формы}
VK_UP: Color := (Color + $050505) and $FFFFFF;
{при нажатии стрелки вниз уменьшим яркость цвета формы}
VK_DOWN: Color := (Color - $050505) and $FFFFFF;
//при нажатии клавиши Escape программа выводит окошко
//с предложением завершить работу
VK_ESCAPE: begin
if Application.MessageBox('Закончить работу с программой?',
'Пример №4', MB__YESNO or MB_ICONQUESTION) = IDYES then Close;
end;
{при нажатии Fl выводится подсказка о работе с программой}
VK_F1: Application.MessageBox(
'1. Стрелка вверх -- увеличение яркости.'#13#10 +
'2. Стрелка вниз -- уменьшение яркости.'#13#10 +
'3. Escape -- выход из программы.'#13#10 +
'4. F1 — справка.',
'Справка', МВ_ОК or MB_ICONINFORMATION);
Рис. 4. Результат нажатия клавиши Escape
Рис. 5. Результат нажатия клавиши F1
8
IrJPalnt.
В мультизадачной операционной системе, такой, как Windows, обычно
несколько программ одновременно выводят информацию на единственный в системе монитор.
Для того, чтобы не возникало путаницы: где какой программе рисовать, — были придуманы
- -а. Каждая программа может создать для себя одно или несколько окон. Окно состоит из
. темной области, к которой относятся заголовок, рамка, строка состояния, полосы прокрутки
и рабочей области, в которую выводится полезная информация. Хотя окна на экране выглядят
как вполне самостоятельные объекты, их изображения на самом деле хранятся в одной общей
области видеопамяти. Когда какое-нибудь окно всплывает наверх, его невидимая часть рисуется
заново и затирает изображения других окон, которые оказались под ним. Окна — это
логические объекты и их работа практически полностью обеспечивается операционной
системой. Она отвечает за рисование системной области, заполнение рабочей области фоновым
цветом, за перемещение, изменение размера окна и пр. Прикладная программа свободна от всех
этих забот и должна решать только свою непосредственную задачу.
Для того, чтобы информировать программу о необходимости заново сформировать изображение в
рабочей области окна, используется событие ОпРаint (ему соответствует сообщение WM_PAINT).
Оно происходит сразу, как только в рабочей области окна появляется незаполненный участок.
Причиной этого может быть, например, увеличение размера окна или же изменение его положения
относительно других окон. На рис. 6 показан круг, нарисованный по щелчку мышкой в обработчике
события OnClick. Его частично закрыли другим окном, а затем это окно убрали на задний план.
Операционная система восстановила изображение рамки и фон рабочей области в ставшей теперь
видимой части окна. Но изображение круга так и осталось неполным. Для того, чтобы восстановить
его, нужно снова щелкнуть мышкой для генерации события OnClick.
рисование круга в обработчике события OnClick
procedure TForml.FormClick(Sender: TObject);
Canvas .Pen.Color := clGreen;
Canvas.Brush.Color := clGreen; Canvas.Ellipse
(60, 10, 2 9 0 , 2 4 0 ) ; e n d ;
На рис. 7 показан тот же круг, с которым проделали то же самое: он был закрыт другим
окном. а затем это окно убрали на задний план. Операционная система восстановила рамку и
фон окна и поместила в очередь сообщений программы сообщение WM_PAINT. В результате
9 было зафиксировано событие OnPaint и был
вызван его обработчик. Он нарисовал круг заново. Все эти действия обычно происходят
настолько быстро, что у пользователя создается впечатление, что окна — это тонкие
пластинки, которые просто меняются местами.
Рис. 6. Круг, нарисованный в обработчике события OnClick
Рис. 7 Круг, нарисованный в обработчике события OnPaint
10
рисование круга в обработчике события OnPaint
procedure TForml.FormPaint(Sender: TObject);
begin
Canvas.Pen.Color := clGreen;
Canvas.Brush.Color := clGreen;
Canvas.Ellipse (60, 10, 290, 240);
2. Контекст устройства. Объект «холст» класса TCanvas
Приложения Windows осуществляют вывод графической информации на экран или принтер с
помощью функций GDI (Graphics Device Interface —Интерфейс графических устройств). Сама
операционная система Windows для отображения информации также использует функции GDI.
Функции GDI являются аппаратно-независимыми. Поэтому при выводе графической
информации приложение работает не с физическим, а логическим устройством, имеющим высокие
характеристики: широкая цветовая палитра, большое разрешение и т.п. Взаимодействие приложения
с устройствами вывода осуществляется с помощью драйверов, которые преобразуют вызовы
аппаратно-независимых функций GDI в команды конкретного jстройства.
При выполнении запроса приложения на вывод информации GDI или драйвер учитывают
ограниченные возможности и особенности физического устройства и выполняют коррекцию
выводимой информации. Например, приложение может указать для цвета геометрической фигуры
любой из примерно 16,7 миллионов цветов (2 ), однако далеко не всякое физическое устройство (в
частности, струйный принтер) обладает такими богатыми возможностями отображения цвета.
Поэтому фигура будет закрашена наиболее близким к запрошенному цветом, который
поддерживается конкретным устройством.
Такой подход позволяет приложениям и операционной системе Windows функционировать
независимо от особенностей периферийного оборудования. Приложения Windows способны работать
на компьютерах практически любой конфигурации, при этом чем лучше будут характеристики
аппаратной части, тем больше выводимая информация будет соответствовать требованиям
приложения.
Взаимодействие приложения с драйвером устройства осуществляется через специальную
структуру данных, которая используется функциями GDI. Эта структура называется контекстом
устройства (Device Context — DC) и содержит основные характеристики устройства вывода, а также
инструменты для рисования. К контексту относятся следующие три инструмента:
• шрифт (определяет вид выводимого текста);
• перо (им рисуются линии и границы фигур);
• кисть (ей осуществляется закраска фигур).
Схематично взаимодействие приложения и устройства вывода можно изобразить схемой,
показанной на рис. 8:
Delphi предлагает специальные классы, существенно упрощающие использование графических
средств:
• TCanvas — для контекста устройства, называемого в Delphi также «холстом»;
• TFont — для шрифта;
11
•
•
TPen — для пера;
TBrush — для кисти.
Рис. 8. Взаимодействие приложения с графическим устройством вывода
Холст имеет большое число свойств и методов, позволяющих отображать графические примитивы
(линии, эллипсы и пр.), выводить изображения или их отдельные части, выводить текстовую
информацию. В их число входят свойства-объекты перо (Pen класса ТРеn), кисть Brush класса
TBrush) и шрифт (Font класса TFont).
Перо (Реп)
Перо используется для рисования отдельных линий и границ замкнутых фигур. Оно имеет
следующие основные свойства:
• Color: TColor — цвет рисуемых линий.
• Width: integer — толщина рисуемых линий.
• Style: TPenStyle — стиль рисуемых линий: сплошная (psSolid), штриховая (psDash),
пунктирная (psDot), штрихнунктирная (psDashDot), чистая, не рисует (psClear) и т.п.
Заданный стиль применяется только если линия имеет толщину в одну точку.
Ниже приводится пример программы, рисующей штрихпунктиром отрезок (0,0) - (350,250)
толщиной в одну точку красного цвета.
Рис. 9. Пример работы со свойствами пера (Реп)
procedure TForml.FormClick(Sender: TObject);
begin
Canvas.Pen.Color := clRed; //красный цвет пера
Canvas.Pen.Width := 1; //перо толщиной в одну точку
Canvas.Pen.Style := psDashDot; //штриховая линия
12
Canvas.MoveTo(0,0); Canvas.LineTo(350,2 5 0 ) ; //рисование линии
Кисть (Brush)
Кисть используется для закрашивания внутренней части замкнутых фигур
(прямоугольников, эллипсов и т.п.) и при заливке ограниченных областей краской (функция
FloodFill). Она имеет следующие основные свойства:
• Color: TColor — цвет закраски.
• Style:TBrushStyle — стиль закраски: сплошная (bsSolid), прямая сетка (bsCross), косая
сетка (bsDiagCross), наклонные линии (bsBDiagonal и bsFDiagonal), горизонитальные
линии (bsHorizontal), вертикальные линии (bsVertical), чистая, не рисует (bsClear).
• Bitmap: TBitmap — двухцветный рисунок размером 8x8 точек. Если задан, то
используется как шаблон при закраске и позволяет задать собственный стиль закраски.
Ниже приводится пример программы, рисующей при щелчке мышкой два круга. Один закрашен с
использованием стандартного стиля кисти, для второго создан шаблон - маленький кружок
обработчик события OnPaint procedure
TForml.FormPaint(Sender: TObject);
bmp : TBitmap;
with Canvas do begin
{'Нарисуем левый круг, используя стандартный стиль закраски}
Pen.Color := clLime; //зеленый цвет для пера
Pen.Width := 3; //перо толщиной 3 точки
Brush.Color := clRed; //красный цвет для кисти
Brush.Style := bsBDiagonal; //закраска наклонными линиями
//рисуется первый круг
Ellipse(10,10,160, 1 6 0 ) ;
{Нарисуем правый круг, используя собственный шаблон для кисти}
//создадим изображение-шаблон
bmp := TBitmap.Create; //создание объекта изображения
bmp.PixelFormat := pf24bit; //формат изображения - TrueColor
bmp.Width := 8; bmp.Height := 8; //размер 8x8 точек
//нарисуем на изображении красный кружок
bmp.Canvas.Pen.Color := clRed; omp.Canvas.Brush.Color :=
clRed;
bmp.Canvas.Ellipse(0, 0, 5, 5); Brush.Bitmap := bmp; //выберем
изображение как шаблон для кисти //рисуется второй круг
Ellipse(17 0,10,320,160);
I
I
//удалим изображение
Brush.Bitmap := nil; bmp.Free;
end
Рис. 10. Использование стандартного и
нестандартного стилей закраски
Шрифт (Font)
Свойства объекта Font определяют начертание текста, выводимого при помощи функций Out и
TextRect. Он имеет следующие основные свойства:
• Color: TColor — цвет букв. Фон под надписью закрашивается кистью.
• Name: TFontName — название шрифта, например, 'Times New Roman'.
• Size: Integer — размер шрифта в пунктах (1/72 дюйма).
• Style: TFontStyles — задает стиль шрифта: толстый (fsBold), наклонный (fsltalic), почеркнутый
(fsUnderline), зачеркнутый (fsStrikeOut). К тексту можно применить одновременно все четыре
стиля. Поэтому TFontStyles — это множественный тип данных. Свойству Style можно
присвоить либо множество, содержащее несколько элементов, либо пустое множество:
Canvas.Font.Style := [fsBold, fsltalic]; //толстый наклонный шрифт Canvas.Font.Style
:= [ ] ; //обычный шрифт (пустое множество)
Рис. 11. Пример использования объекта Font
Ниже приводится пример программы, рисующей синего голубя с помощью шрифта
Webdings. Изображению голубя в этом шрифте соответствует код буквы я в обычных шрифтах.
14
procedure TForml . FormPaint ( Sender : TObject);
with Canvas do begin
Brush.Style := bsClear;
Font.Color := clBlue;
Font.Size := 144;
Font.Name := 'Webdings';
TextOut ( 50,0, 'я') ;
//чистая кисть, фон под текстом не рисуется
//буквы синего цвета
//размер букв -- 144 пункта
//название шрифта
//вывод буквы 'голубь'
3.Примеры работы с классом TCanvas
Пример Ml. Ниже приведен обработчик события OnMouseDown формы, который при
нажатии мышью в любом месте ее рабочей области рисует там жирную точку и рядом выводит
жоординаты курсора мыши. Результат нескольких нажатий показан на рис 12.
*
Рис 12. Реакция обработчика события OnMouseDown на
щелчки мышью по форме
//Оработчик события нажатия кнопки мыши. procedure
TForml.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift:
TShiftState; X, Y: Integer);
with Canvas do begin
Brush.Color := Color;
//цвет знакоместа -- как у формы
Font.Color := clBlue;
//цвет текста -- синий
Font.Size := 10;
//размер шрифта
Font.Name := 'Times New Roman';
//шрифт //стиль начертания =
толстый + наклонный + подчеркнутый Font.Style := [fsBold,
fsltalic, fsUnderline]; //выведем рядом с курсором мыши его
координаты TextOut(х, у, '(' + IntToStr(x) + ',' + IntToStr(y)
+ ')'); //нарисуем под курсором толстую черную точку
Brush.Color := clBlack; //цвет кисти -- черный Pen.Color :=
clBlack;
//цвет пера -- черный Ellipse(х - 3, у - 3, х + 3,
у + 3); //маленький кружок
15
Пример №2. Ниже приведен обработчик события OnPaint формы, который загружает
изображение из файла .bmp и выводит его на форму (рис. 13). Здесь используются свойства
формы ClientWidth и ClientHeight, возвращающие соответственно ширину и высоту ее
рабочей области, а также класс TBitmap, предназначенный для работы с двоичными
изображениями.
Рис. 13. Вывод двоичного изображения
о б р а б о т ч и к события OnPaint procedure
TForml.FormPaint(Sender: TObject);
Pic : TBitmap;
создадим объект-изображение
Pic := TBitMap.Create;
загрузим изображение из файла tulips.bmp
Pic.LoadFromFile('tulips.bmp');
выведем изображение в центре формы Canvas .
Draw ( (ClientWidth - Pic.Width) div 2,
(ClientHeight - Pic.Height) div 2, Pic)
;
освободим память, уничтожив объект-изображение
Pic.Free;
Пример №3. Ниже приведен листинг программы, рисующей с помощью методов класса
TCanvas пейзаж. Для изображения машины и собаки используется шрифт Webdings.. Результат
ее работы показан на рис. 14.
unit Unitl;
interfасе
16
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ComCtrls, ToolWin;
TForml = class(TForm)
procedure FormPaint(Sender: TObject);
private end;
Forml: TForml;
implementation
{$R *.DFM}
//солнечные лучики
SunRays: array[0..10, 0..3] of longint = (
(358, 116, 358, 141), //луч №1
(292,
74, 319, 75), //луч №2
(296,
35, 329, 53),
(327,
98, 299, 117),
(338,
112, 329, 129),
(378,
110, 390, 126),
(359,
33, 359, 14), //...
(384,
43, 399, 26),
17
(337, 38, 333, 29), (398, 93,
419, 103), (396, 54, 411, 45)
//луч №11
Облако №1
cloud0: array[0..10, 0..3] of Longint = (
331, 71, 536,
94), //эллипс №1
356, 81, 409,
58), //эллипс №2
405, 83, 469,
48),
448, 59, 481,
79),
422, 64, 538,
89),
371,
66, 352,
80), //...
514, 85, 550,
75),
392,
64, 418,
55),
345,
98, 389,
79),
531, 96, 459,
78),
392,
81, 464,
103) //эллипс №11
облако №2
Cloud1 :
49,
96,
array[0..6, 0..3] of Longint = (
75, 241, 104), //эллипс №1
59,162, 94),
//эллипс №2
154,
148,
69,194,
63,174,
111,
89,
82),
73),
57, 106)
//...
//эллипс №7
координаты вершин трапеции, изображающей дорогу
Road: array[1..4] of TPoint = ( x:250; y:250),
x:205; y:380), X-.410; y:380),
E
//координаты прямоугольника, изображающего землю
arth: TRect = (Left:0; Top:250; Right:550; Bottom:380); //координаты
прямоугольников, изображающий деревья на горизонте слева и справа от
дороги ТreesL: TRect = (Left:0; Top:235; Right:250; Bottom:250);
ТressR: TRect = (Left:330; Top:235; Right:550; Bottom:250);
обработчик события OnPaint. Вызывается, когда программа должна обновить
//изображение
procedure TForml.FormPaint(Sender: TObject);
_:TRect;
i : Integer;
with Canvas do begin
//Солнце
Brush.Color:=RGB (255,255,0) ; //кисть — желтого цвета
Pen.Color:=RGB(255,255,0);
//перо — желтого цвета
Pen.Width:=1;
//толщина пера -- 1 точка
18
Ellipse(309, 30, 407, 123); //нарисуем круг
?en.Width:=5;
/нарисуем лучи for i := 0 to
10 do begin
MoveTo(SunRays[i, 0], SunRays[i, 1 ] ) ;
LineTo(SunRays[i, 2], SunRays[i, 3]);
end;
■
■облака
Brush.Color:=clWhite; //кисть -- белого цвета
Pen.Color:=clWhite;
//перо — белого цвета
Pen.Width:=1;
//толщина пера -- 1 точка
нарисуем эллипсы, из которых состоит первое облако for i
:= 0 to High(CloudO) do
Ellipse(Cloud0[i, 0], Cloud0[i, 1], CloudO[i, 2], CloudO[i, 3]);
нарисуем эллипсы, из которых состоит второе облако for i := 0 to
High(Cloudl) do
Ellipse(Cloud1[i, 0], Cloudl[i, 1], Cloudl[i, 2], Cloudl[i, 3]);
//земля Pen.Color:=RGB(0,90,0); //перо -- темнозеленое Brush.Color:=RGB(0,90,0); //кисть -- темнозеленая EillRect(Earth);
деревья на горизонте слева и справа от дороги
Pen.Color:=RGB(0,120,0); //перо -- светло-зеленое
Brush.Color:=RGB(0,120,0); //кисть -- светло-зеленая
FillRect(TreesL); FillRect(TreesR);
//асфальтированная дорога Pen.Color:=clGray;
//перо серого цвета Brush.Color:=clGray;
//кисть серого цвета Polygon(Road);
//белая разделительная полоса
Pen.Color := clWhite;
Pen.Style := psDash; //пунктирная линия
MoveTo)(Road[l].x + Road[4].x) div 2,(Road[l].у + Road[4].y) div 2);
LineTo((Road[2].x + Road[3].x) div 2,(Road[2].y + Road[3].y) div 2);
MoveTo((Road[1].x + Road[4].x) div 2 - 1 , (Road[l].y + Road[4].y) div 2);
LineTo((Road[2].x + Road[3].x) div 2 - 1 , (Road[2].y + Road[3].y) div 2);
MoveTo((Road[1].x + Road[4].x) div 2 + 1 , (Road[l].y + Road[4].y) div 2);
LineTo( (Road[2] .x + Road[3].x) div 2 + 1, (Road[2].y + Road[3].y) div 2);
нарисуем машину на дороге при помощи шрифта Webdings
Font.Color := clBlack; //буквы черного цвета Brush.Style
:= bsClear; //фон под текстом не рисуется Font.Size := 45;
//размер шрифта = 60 пунктов Font.Name :=
'Webdings';//название шрифта
выведем английскую букву 'р', код которой соответствует
//машине в шрифте Webdings TextOut(235, 250, 'р');
//нарисуем собаку
Font.Size := 30; TextOut(340, 320, 'х');
end; ■
19
Пример №4. Ниже приведен листинг программы, рисующей вазу с цветком (рис. 15).
Плавные линии изображаются при помощи кривых Безье (процедура PolyBezier). После того.
■ для каждого элемента рисунка, например, листа или вазы, вырисовывается контур, его
внутренняя часть "заливается краской" с помощью процедуры FloodFill. Таким образом можно
закрашивать объекты произвольной формы. При нажатии клавиши Пробел включается и
выключается выделение точек, по которым строились все кривые Безье, а также соединяющих
их пунктирных линий (рис. 16 ).
Рис. 15. Рисование плавных контуров кривыми
Безье
Рис.16. Точки, определяющие кривые Безье,
соединены пунктирными линиями и
отмечены красными кружками
Unit main;
interfасе
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
TForml = class(TForm)
procedure FormPaint(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState); private
{ Private declarations }
public
{ Public declarations }
20
end;
var
Forml: TForml;
implementation
{$R * .dfm}
var
//если флаг ShowPts равен true, то точки, по которым
//рисовались кривые Безье, соединяются пунктирными линиями
ShowPts : boolean = false;
{множества точек, определяющие кривые Безье}
//левая часть контура вазы pi: array[1..7] of
TPoint = (
(х:150; у:250),
(х:175; у:275),
(х:175; у:300),
(х:150; у:325),
(х:125; у:350),
(х:125; у:400),
(х : 17 5 ; у: 4 2 5 )
) ;
//правая часть контура вазы р2:
array[1..7] of TPoint = (
(х:222; у:250),
(х:200; у:275),
(х:200; у:300),
(х:225; у:325),
(х:250; у:350),
(х:250; у:400),
(х:200; у:425)
);
//стебелёк
рЗ: array[1..4] of TPoint = (
( х : 186; у:246),
(х:186; у:150),
(х:160; у: 50),
(х:109; у:138)
);
//цветок
р4: array[1..7] of TPoint = (
(х: 53; у:167),
(х: 70; у:170),
(х:100; у:110),
(х:109; у: 138 ) ,
(х: 138 ; у: 135) ,
(х:100; у:190),
(х:110; у:200)
);
//ломаная линия -- нижняя часть цветка р5:
array[1..5] of TPoint = ( (х: 53; у:167),
(х: 72;
(х: 81;
(х:100;
(х:110;
у:170),
у:183),
у:186),
у:200;
//правый лист
р6: array[1..7] of Tpoint = (
(х:186; у:225),
(х:205; у:160),
(х:219; у:153),
(х:262; у:175),
(х:246; у:165),
(х:205; у:170),
(х:186; у:225) )
;
//левый лист
р7: array[1..7] о£ TPoint = (
(х:186; у:225),
(х:154; у:187),
(х:130; у:215),
(х:112; у:252),
(х:142; у:21Э),
(х:167; у:205),
(х:186; у:225) )
;
//Обработчик события OnPaint. Вызывается, когда программа
//должна обновить изображение
procedure TForml.FormPaint(Sender: TObject);
var i : byte;
begin
with Canvas do begin
{выведем надпись}
Brush.Color := Color; //цвет кисти = цвету формы
Font.Size := 12; //размер шрифта
Font.Name := 'Comic Sans MS'; //название шрифта
//выведем надпись
TextOut(40,10,'Пробел -- показать/спрятать линии');
{нарисуем силуэт вазы}
//установим цвет и ширину пера
Pen.Color := clBlue; Pen.Width := 4;
//левая кривая
PolyBezier(pi);
//правая кривая
PolyBezier(p2);
//верхняя горизонтальная линия, ограничивающая вазу
MoveTo(pl[1] .х, pl[l].y); LineTo (р2 [ 1] . х, р2[1].у);
//нижняя линия горизонтальная линия, ограничивающая вазу
MoveTo(pl[7].х, pl[7].y); LineTo(p2[7].х, р2[7].у);
//зальем внутреннюю часть вазы тем же цветом, какой имеет ее контур
Brush.Color := clBlue; //установим цвет кисти
FloodFill(pi[3].х+5, pl[3].y, clBlue, fsBorder); //выполним заливку
{нарисуем стебелёк}
Pen.Color := clGreen; //перо - зеленого цвета
PolyBezier (рЗ);
22
{нарисуем цветок}
Pen.Color := $00C080FF; //перо -- кремового цвета
PolyBezier(р4); //нарисуем верхнюю часть цветка плавной линией
PolyLine(р5); //нарисуем нижнюю часть цветка линией с изломами
Brush.Color := $00C080FF; //кисть -- кремового цвета
//зальем внутреннюю часть цветка кремовой краской
FloodFill(р5[2].х+5, р5[2].у, $00C080FF, fsBorder);
{нарисуем правый лист}
Pen.Color := clGreen; //перо -- зеленого цвета
Pen.Width := 3; //ширина пера -- 3
PolyBezier(рб); //нарисуем корнут листа
Brush.Color := clGreen; //кисть -- зеленого цвета
//зальем внутренность листа зеленой краской
FloodFill(222, 172, clGreen, fsBorder);
{нарисуем левый лист}
PolyBezier(p7); //контур листа
FloodFill(150, 213, clGreen, fsBorder); //закраска внутренней части
{если флаг ShowPts = true, то нарисуем линии, соединяющие точки, по
которым рисовались кривые Безье и отметим их красными кружками} if
ShowPts = true then begin
//нарисуем ломаные линии
Pen.Color := clBlack; Pen.Style := psDot; Brush.Color := Color;
Pen.Width := 1;
Polyline(pi);
Polyline(p2);
Polyline(p3);
Polyline(p4);
Polyline(рб);
Polyline(p7);
//отметим точки красными кружками
Pen.Color := ciRed;
Brush.Color := clRed;
for i:= 0 to length(pi) do
Ellipse(pi[i].x-3, pl[i].y-3, pl[i].x+3, pl[i].y+3);
for i:= 0 to length(p2) do
Ellipse(p2 [i] .x-3, p2[i].y-3, p2[i].x+3, p2[i].y+3);
for i:= 0 to length(p3) do
Ellipse(p3[i1.x-3, p3[i].y-3, p3[i].x+3, p3[i].y+3);
for i:= 0 to length(p4) do
Ellipse(p4[i].x-3, p4[i].y-3, p4[i].x+3, p4[i].y+3);
for i:= 0 to length(p6) do
Ellipse(рб[i].x-3, p6[i].y-3, p6[i].x+3, p6[i].y+3);
for i:= 0 to length(p7) do
Ellipse(p7[if.x-3, p7[i].y-3, p7[i].x+3, p7[i].y+3); end;
end end;
//Обработчик события OnKeyDown. Вызывается при нажатии клавиши на клавиатуре,
procedure TForml.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
//если нажата клавиша Пробел, то переключим показ линий, соединиящих точки,
//по которых строились кривые Безье
23
if Key = VK__SPACE then begin
ShowPts := not ShowPts; //изменим значение ShowPts на противоположное
refresh //обновим рисунок
end; end;
end.
4. Задание
1. Изучить
основные
графическими
события,
программами
используемые
(OnClick,
для
OnDblClick,
управления
OnMouseDown,
интерактивными
OnMouseMove,
OnMouseUp, OnResize, OnKeyPress, OnKeyDown, OnKeyUp, OnCreate), параметры их
обработчиков, свойства и методы классов TCanvas, TPen, TBrush и TFont.
2. Создать на листе бумаги или в графическом редакторе рисунок, состоящий из
графических примитивов (линий, дуг, отрезков прямых, окружностей и пр.) и найти
координаты определяющих их точек.
3. Создать
программу,
формирующую
заданное
изображение
на
экране
компьютера.
Изображение должно сохраняться при изменении размера окна программы или при
перекрытии его другими окнами. Для этого оно должно формироваться в обработчике
события OnPaint.
Варианты задания
1. Разноцветная парусная яхта.
2. Разноцветный вертолет с бортовым номером (цифры нарисовать при помощи функции
вывода текста).
3. Разноцветный будильник с надписью «Восток».
4. Разноцветные стол и стул.
5. Разноцветный компьютер с надписью «Pentium-IV».
6. Разноцветный домик с надписью «Булочная».
7. Разноцветная коробка с надписью «Не кантовать».
8. Разноцветная открытка с елочкой и с надписью «С новым годом!».
9. Три разноцветных воздушных шарика на нитках с цифрами 1, 2 и 3 (цифры нарисовать
подходящим шрифтом и цветом).
10. Разноцветный истребитель в виде сверху.
24
11. Раскрашенная милицейская машину с мигалкой.
12. Раскрашенная разными цветами подводная лодка с рубкой и иллюминаторами.
13. Цветной домике полукруглым чердачным окошком.
14. Крыша домика и яблоня за забором.
15. Работающий фонтан.
16. Скорая помощь с красным крестом и мигалкой.
17. Разноцветный паровозик.
18. Раскрашенная ракета на старте под звездным небом.
19. Разноцветный фургон с надписью «Хлеб».
20. Разноцветная настольная лампа.
21. Разноцветные весы с чашечками и с гирей.
22. Разноцветный чайник
23. Разноцветный самовар.
24. Разноцветный утюг и столик для глажения.
25. Маяк на утесе над морем.
5. Контрольные вопросы
1. Какая цветовая схема применяется в мониторе? Какие в ней используются основные цвета?
Приведите примеры получения смешанных цветов.
2. Какие способы можно использовать в Delphi для определения цвета графических
объектов?
3. Какая цветовая схема используется в цветных принтерах? Какие в ней используются
основные цвета? Приведите примеры получения смешанных цветов.
4. Что такое основной цвет и дополнительный цвет в цветовых схемах?
5. Какая теория лежит в основе трехкомпонентных цветовых схем?
6. В каких режимах может работать видеоподсистема персонального компьютера?
7. Опишите структуру видеопамяти в цветном текстовом режиме работы видеоадаптера.
8. Опишите структуру видеопамяти в графическом режиме с палитрой (256 цветов).
9. Опишите структуру видеопамяти в графическом режиме без палитры (TrueColor).
10. Нарисуйте экранную систему координат, установленную по умолчанию и объясните, каким
образом задаются координаты пикселов.
25
11. Основные события, используемые для управления интерактивной графической программой:
OnClick, OnDblClick, OnMouseDown, OnMouseMove, OnMouseUp. OnResize. OnKeyPress,
OnKeyDown, OnKeyUp, OnCreate. Основные параметры их обработчиков.
12. При помощи какого события программа может узнать о нажатии клавиш 'Пробел'. 'А'. '9'. F1,
'F12', 'Escape', '<-','->'?
13. При помощи какого события программа может узнать координаты курсора мыши.
14. При помощи какого события программа может узнать, какая кнопка нажата у мышки?
15. При помощи каких событий программа может узнать о том, когда пользователь нажал и когда
отпустил кнопку мыши?
16. При помощи какого события программа может узнать о двойном щелчке мышью?
17. Понятие обработчика события. Создание обработчиков событий.
18. Контекст устройства, его назначение. Объект "холст" класса TCanvas, его свойства и методы.
19. Средства, предоставляемые GDI для рисования линий и точек.
20. Средства, предоставляемые GDI для рисования замкнутых областей и их закрашивания.
21. Средства, предоставляемые GDI для вывода текста.
22. Что такое области формы с действительным и недействительным содержимым? Для чего
предназначено событие OnPaint?
23. Чем определяется цвет контура и цвет заливки при рисовании фигуры?
24. Какие свойства имеет перо?
25. Какие свойства имеет кисть?
26. Каким образом «перекрасить» красный многоугольник в зеленый цвет, если известны
координаты точки, расположенной внутри него?
Download