Работа 6
ГРАФИЧЕСКИЙ РЕДАКТОР
Цель работы:
- создать простейший графический редактор
- закрепить основные операции графического вывода в Delphi;
- закрепить навыки составления, отладки и тестирования программ.
I. Теоретический раздел работы
Обзор компонент
Программирование графики в Windows является достаточно сложным и трудоемким процессом, но Delphi и здесь приходит на помощь программисту и предлагает специальные классы, существенно упрощающие использование графических средств. Рассмотрим классы, которые могут понадобиться для создания графического редактора:
- TImage
- TPicture
- TBitmap
Графический образ TImage
TImage позволяет поместить графическое изображение в любое место на форме. Этот объект очень прост в использовании - выберите его на странице Additional и поместите в нужное место формы.
Важными являются свойства объекта Canvas и Picture. Свойство Canvas позволяет создавать и редактировать изображения. Свойство Picture (которое является объектом типа TPicture со своим набором свойств и методов) содержит отображаемый графический объект типа битовой матрицы.
Класс TPictures
Объект типа TPicture является контейнером любого графического объекта TGraphic, тип которого указывается свойством Graphic. Объект TPicture имеет методы файлового чтения и записи LoadFromFile и SaveToFile, автоматически подстраивающиеся под тип объекта.
Метод LoadFromFile(FileName) читает файл FileName и загружает его в графический объект. Если формат графического файла не зарегистрирован, или не соответствует типу графического объекта, то генерируется исключение EInvalidGraphic.
Метод SaveToFile(FileName) сохраняет изображение графического объекта в файле FileName.
Рассмотрим загрузку картинки во время выполнения программы. Это можно сделать, например, так:
if OpenDialog1.Execute then
Image1.Picture.LoadFromFile (OpenDialog1.FileName);
Обмен объекта TPicture с буфером обмена Clipboard может осуществляться методом Assign объекта TClipboard.
Класс TBitmap
Класс TBitmap инкапсулирует битовую матрицу Windows, включая палитру. Обеспечивает быстрое и простое для пользователя выполнение операций создания, копирования, манипулирования и сохранения битовой матрицы. Для нас важными будут лишь свойства Width и Height – ширина и высота матрицы.
Компонент TSpeedButton
Компонент TSpeedButton используется для кнопок с фиксацией. Имеет возможность отображения пиктограмм и может использоваться как обычная управляющая кнопка или как кнопка с фиксацией нажатого состояния. Обычно используется в качестве быстрых кнопок, дублирующих различные команды меню, и в инструментальных панелях.
У кнопок TSpeedButton, как и у других кнопок, имеется свойство Caption - надпись, но в этих кнопках оно обычно оставляется пустым, так как вместо надписи используется пиктограмма. Изображение на кнопке задается свойством Glyph точно так же, как для кнопок TBitBtn. И точно так же свойство NumGlyphs определяет число используемых пиктограмм, свойства Layout и Margin определяют расположение изображения, а свойство Spacing - расстояние между изображением и надписью (если, конечно, вы все-таки хотите использовать надпись на кнопке).
Имейте ввиду что при выводе каждой из пиктограмм(частей картинки) на кнопку левый нижний пиксель и все точки того же цвета становятся прозрачными и не видны на кнопке.
Режимы рисования пером на канве
Свойство пера Mode определяет, каким образом взаимодействуют цвета пера и канвы. Выбор значения Mode позволяет получать различные эффекты.
Некоторые возможные значения Mode:
pmNot - Инверсный по отношению к цвету фона канвы
pmCopy - Цвет, указанный в свойстве Color пера Pen: это значение принято по умолчанию
pmNotCopy - Инверсия цвета пера
pmXor - Операция XOR: комбинация цветов пера и фона канвы по принципу XOR.
pmNotXor - Инверсия режима pmXor: комбинации цветов или пера, или фона канвы, но не обоих.
Режимы pmXor и pmNotXor примечательны тем, что позволяют “показывать” и “скрывать” графический объект. Первый вывод на канву хотя в общем случае и искажает цвета, все же помогает судить о расположении объекта. Повторный вывод на канву той же фигуры восстанавливает изображение, которое было до первого вывода. Эти свойства можно использовать, например, при перемещении фигуры.
II. Экспериментальный раздел работы
Пример1: Цель данного занятия – создать простой графический редактор. При помощи мыши мы сможем рисовать произвольные кривые, прямые, эллипсы, прямоугольники, прямоугольники с закругленными углами и, наконец, сможем закрашивать области некоторым цветом. Программа сможет открывать и сохранять изображения в формате bmp.
Поместите на форму объекты типа TImage и TMainMenu. Создайте пункт меню Tools и в нем подпункты Pen, Line, Ellipse, Rectangle, Roundrect, Flood Filling. Данный пункт меню будет использоваться для выбора текущего инструмента рисования.
procedure TForm1.pen1Click(Sender: TObject);
begin
pen1.Checked:=true;
line1.Checked:=false;
Ellipse1.Checked:=false;
Rectangle1.Checked:=false;
Roundrect1.Checked:=false;
FloodFilling1.Checked:=false;
end;
procedure TForm1.line1Click(Sender: TObject);
begin
pen1.Checked:=false;
line1.Checked:=true;
Ellipse1.Checked:=false;
Rectangle1.Checked:=false;
Roundrect1.Checked:=false;
FloodFilling1.Checked:=false;
end;
procedure TForm1.Ellipse1Click(Sender: TObject);
begin
pen1.Checked:=false;
line1.Checked:=false;
Ellipse1.Checked:=true;
Rectangle1.Checked:=false;
Roundrect1.Checked:=false;
FloodFilling1.Checked:=false;
end;
procedure TForm1.Rectangle1Click(Sender: TObject);
begin
pen1.Checked:=false;
line1.Checked:=false;
Ellipse1.Checked:=false;
Rectangle1.Checked:=true;
Roundrect1.Checked:=false;
FloodFilling1.Checked:=false;
end;
procedure TForm1.Roundrect1Click(Sender: TObject);
begin
pen1.Checked:=false;
line1.Checked:=false;
Ellipse1.Checked:=false;
Rectangle1.Checked:=false;
Roundrect1.Checked:=true;
FloodFilling1.Checked:=false;
end;
procedure TForm1.FloodFilling1Click(Sender: TObject);
begin
pen1.Checked:=false;
line1.Checked:=false;
Ellipse1.Checked:=false;
Rectangle1.Checked:=false;
Roundrect1.Checked:=false;
FloodFilling1.Checked:=true;
end;
Для рисования текущей фигуры напишем процедуру DrawShape(не забудьте добавить её описание в раздел Public класса TForm1):
procedure TForm1.DrawShape(TopLeft, BottomRight: TPoint;Amode: TpenMode);
begin
with Image1.Canvas do
begin
Pen.Mode:= AMode;
if pen1.Checked then
begin
LineTo(BottomRight.X, BottomRight.Y);
Pixels[BottomRight.X, BottomRight.Y]:=Pen.Color;
end;
if line1.Checked then
begin
MoveTo(TopLeft.X, TopLeft.Y);
LineTo(BottomRight.X, BottomRight.Y);
end;
if Ellipse1.Checked then
Ellipse(Topleft.X, TopLeft.Y, BottomRight.X,BottomRight.Y);
if Roundrect1.Checked then
Rectangle(TopLeft.X, TopLeft.Y, BottomRight.X,BottomRight.Y);
if Roundrect1.Checked then
RoundRect(TopLeft.X, TopLeft.Y, BottomRight.X,
BottomRight.Y, (TopLeft.X - BottomRight.X) div 2,
(TopLeft.Y - BottomRight.Y) div 2);
if FloodFilling1.Checked then
FloodFill(BottomRight.x,BottomRight.y,pixels[BottomRight.x,BottomRight.y],fsSurface);
end;
end;
Аргументы TopLeft и BottomRight типа TPoint содержат координаты верхнего левого и нижнего правого угла соответственно, аргумент AMode задает режим рисования пера. записываем код для того чтобы один инструмент работал другой был не рабочий.
procedure TForm1.FormCreate(Sender: TObject);
var
Bitmap: TBitmap;
begin
Caption:='Draw program';
Bitmap:= nil;
try
Bitmap:= TBitmap.Create;
Bitmap.Width:= Form1.Width;
Bitmap.Height:=Form1.Height;
Image1.Picture.Graphic:= Bitmap;
Image1.Width:=Bitmap.Width;
Image1.Height:=Bitmap.Height;
finally
Bitmap.Free;
end;
Image1.canvas.brush.style:=bsclear;
pen1.Checked:=true;
end;
Для отслеживания траекторий мыши напишем обработчики Image1MouseDown, Image1MouseMove, Image1MouseUp.
procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Drawing then
begin
DrawShape(Origin, Point(X, Y), pmCopy);
Drawing:= False;
end;
end;
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Drawing:= True;
Image1.Canvas.MoveTo(X, Y);
Origin:= Point(X, Y);
MovePt:= Origin;
end;
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if Drawing then
if (Pen1.Checked)or(FloodFilling1.Checked) then
begin
MovePt:= Point(X, Y);
DrawShape(Origin, MovePt, pmCopy);
end else begin
DrawShape(Origin, MovePt, pmNotXor);
MovePt:= Point(X, Y);
DrawShape(Origin, MovePt, pmNotXor);
end;
end;
Усовершенствуем нашу программу, добавив возможность открывать и сохранять изображения в файле. Поместите на форме стандартные диалоги TSavePictureDialog и TOpenPictureDialog. Добавьте пункт меню File с подпунктами New, Open, Save as, Exit и допишите соответствующие обработчики:
procedure TForm1.New1Click(Sender: TObject);
var
Bitmap: TBitmap;
begin
Image1.Picture:= nil;
end;
procedure TForm1.Open1Click(Sender: TObject);
begin
if OpenPictureDialog1.Execute then
image1.Picture.LoadFromFile(openpicturedialog1.FileName);
end;
procedure TForm1.Saveas1Click(Sender: TObject);
begin
if SavePictureDialog1.execute then
begin
Caption:=SavePictureDialog1.FileName;
Image1.Picture.Graphic.Savetofile(Caption);
Image1.Picture.Graphic.Modified:= false;
end;
end;
procedure TForm1.Exit1Click(Sender: TObject);
begin
Close;
end;
Для более полной функциональности приложения добавим пункты меню, меняющие цвет пера и кисти. Разместите на форме стандартный диалог TColorDialog находящийся на странице Dialogs. Добавьте пункт меню Color с подпунктами Pen color и Brush color после чего допишите соответствующие обработчики:
procedure TForm1.Pencolor1Click(Sender: TObject);
begin
If colorDialog1.Execute then
Image1.canvas.pen.color:= ColorDialog1.Color;
end;