Лабораторная работа №12. Создание простейшего графического редактора — КиберПедия 

Опора деревянной одностоечной и способы укрепление угловых опор: Опоры ВЛ - конструкции, предназначен­ные для поддерживания проводов на необходимой высоте над землей, водой...

Своеобразие русской архитектуры: Основной материал – дерево – быстрота постройки, но недолговечность и необходимость деления...

Лабораторная работа №12. Создание простейшего графического редактора

2019-07-12 89
Лабораторная работа №12. Создание простейшего графического редактора 0.00 из 5.00 0 оценок
Заказать работу

 

Цель: Изучение компонентов Image, ScrollBox, компонетов-диалогов, а также обработки событий мыши.

Краткие теоретические сведения.

Компонент Image представляют собой некоторую ограниченную поверхность с канвой, на которую можно заносить изображения. Свойства и методы работы с канвой описаны в Л/р№4.

Компонент Image используется для отображения графики: пиктограмм, битовых матриц и метафайлов. Для этого служит его свойство Picture — объект типа TPicture. Если установить свойство AutoSize в true, то размер компонента Image будет автоматически подгоняться под размер помещенной в него картинки. Если же свойство AutoSize установлено в false, то изображение может не поместиться в компонент или, наоборот, площадь компонента может оказаться много больше площади изображения. Другое свойство — Stretch позволяет подгонять не компонент под размер рисунка, а рисунок под размер компонента

Свойство — Center, установленное в true, центрирует изображение на площади Image, если размер компонента больше размера рисунка.

Рассмотрим еще одно свойство — Transparent (прозрачность). Если Transparent равно true, то изображение в Image становится прозрачным. Это можно использовать для наложения изображений друг на друга.

ScrollBox — панель с прокруткой. Этот компонент предназначен для создания области, в которой могут размещаться компоненты, занимающие площадь большую, чем сам ScrollBox. Если размеры ScrollBox меньше, чем размещенные компоненты, то появляются полосы прокрутки, которые позволяют пользователю перемещаться по всем размещенным в ScrollBox компонентам.

Свойства компонентов OpenPictureDialog и SavePictureDialog ничем не отличаются от свойств компонентов OpenDialog и SaveDialog. Единственное отличие — заданное значение по умолчанию свойства Filter в OpenPictureDialog и SavePictureDialog. В этих компонентах заданы следующие фильтры:

 

All (*.jpg; *.jpeg; *.bmp; *.ico; *.emf; *.wmf) *.jpg; *.jpeg; *.bmp; *.ico; *.emf; *.wmf
JPEG Image File (*.jpg) *.jpg
JPEG Image File (*.jpeg) *.jpeg
Bitmaps (*.bmp) *.bmp
Icons (*.ico) *.ico
Enhanced Metafiles (*.emf) *.emf
Metafiles (*.wmf) *.wmf

 

В этих фильтрах перечислены все типы графических файлов, с которыми может работать диалог. Так что вам остается удалить, если хотите, фильтры тех файлов, с которыми вы не хотите работать, добавить, может быть, фильтр «Все файлы (*.*)» и перевести на русский язык названия типов.

Компонент ColorDialog вызывает диалоговое окно выбора цвета. В нем пользователь может выбрать цвет из базовой палитры или, нажав кнопку Определить цвет, раскрыть дополнительную панель, позволяющую синтезировать цвет, отличный от базовых. Синтезированный цвет можно добавить кнопкой Добавить в набор в палитру дополнительных цветов на левой панели и использовать его в дальнейшем.

События мыши

 

Событие

Описание

 

onClick

Щелчок мыши на компоненте и некоторые другие действия пользователя

 
 

onDblClick

Двойной щелчок мыши на компоненте

 

onMouseDown

Нажатие клавиши мыши на компоненте. Возможно распознавание нажатой кнопки и координат курсора мыши

 

onMouseMove

Перемещение курсора мыши над компонентом. Возможно распознавание нажатой кнопки и координат курсора мыши

 

onMouseUp

Отпускание ранее нажатой мыши над компонентом. Возможно распознавание нажатой кнопки и координат курсора мыши

 

onStartDrag

Начало процесса «перетаскивания» объекта. Возможно распознавание перетаскиваемого объекта

 

onDragOver

Перемещение «перетаскиваемого» объекта над компонентом. Возможно распознавание перетаскиваемого объекта и координат курсора мыши

 

onDragDrop

Отпускание ранее нажатой кнопки мыши после «перетаскивания» объекта. Возможно распознавание перетаскиваемого объекта и координат курсора мыши

 

onEndDrag

Еще одно событие при отпускании ранее нажатой кнопки мыши после «перетаскивания» объекта. Возможно распознавание перетаскиваемого объекта и координат курсора мыши

 

onEnter

Событие в момент получения элементом фокуса в результате манипуляций мышью, нажатия клавиши табуляции или программной передачи фокуса

 

onExit

Событие в момент потери элементом фокуса в результате манипуляций мышью, нажатия клавиши табуляции или программной передачи фокуса

         

 

Во все события, связанные с мышью, передаются также координаты курсора X и Y. Эти параметры определяют координаты курсора в клиентской области компонента. Благодаря этому можно обеспечить различную реакцию в зависимости от того, в какой части клиентской области расположен курсор.

Ход работы

1. Создадим новое приложение и сохраним его в своей папке.

2. Разместим на форме 4 компонента Button и зададим им соответствующие названия. Далее разместим на форме компонент ScrollBox (вкладка Additional). Выделив этот компонент, разместим на нем компонент Image. В свойстве Align этого компонента выберем alClient

 

 

Разместим на форме также два невизуальных компонента – OpenPictureDialog и SavePictureDialog. В этих компонентах свойство Filter уже содержит фильтры для некоторых типов графических файлов. Все эти фильтры, кроме фильтра для bmp-файлов, надо удалить. В свойстве DefaultExt обоих компонентов введем bmp.

3. Создадим еще одну форму и разместим на ней компоненты Button, Label и SpinEdit следующим образом:


 

Для компонентов SpinEdit здадим следующие свойства:

SpinEdit1: MinValue = 10, MaxValue = 800, Increment = 10

SpinEdit2: MinValue = 10, MaxValue = 600, Increment = 10

Первый из них будет определять ширину нового изображения в пикселях, второй – высоту.

Для кнопок определим следующие свойства:

Button1: ModalResult=mrOK, Default = True.

Button2: ModalResult=mrCancel, Cancel = True.

4. Вернемся к первой форме. Создадим обработчик OnClick для кнопки New:

with form2 do //устанавливаем значения счетчиков на второй форме равными текущим значениям ширины и высоты компонента Image

begin

spinedit1.Value:=image1.Width;

spinedit2.Value:=image1.Height;

end;

if form2.ShowModal=mrOK then //если на 2-й форме нажата кнопка ОК

with image1 do

begin

picture:=nil; //очистка прежнего изображения и создание нового с нужными размерами

picture.Bitmap.Width:=form2.SpinEdit1.Value;

picture.Bitmap.Height:=form2.SpinEdit2.Value;

canvas.FillRect(canvas.ClipRect); //заливка созданного изображения цветом фона

savepicturedialog1.FileName:='';

form1.Caption:='Image editor';

end;

5. Создадим обработчик OnClick для кнопки Open:

with openpicturedialog1 do

if execute then

begin

image1.Picture.LoadFromFile(filename);

savepicturedialog1.FileName:=filename;

form1.Caption:='Image Editor - '+Filename; //к заголовку окна добавляется название файла

filename:='';

end;

6. Аналогичным образом создаем обработчик для кнопки Save:

with savepicturedialog1 do

if execute then

begin image1.Picture.SaveToFile(filename);

form1.Caption:='Image Editor -'+ filename;

end;

7. Для копки Clear создадим следующий обработчик:

with image1.Canvas do

fillrect(cliprect);

8. Создадим обработчик события OnCreate для формы:

image1.Parent.DoubleBuffered:=true;

with image1 do

begin

picture.Bitmap.Width:=scrollbox1.Width;

picture.Bitmap.Height:=scrollbox1.Height;

canvas.FillRect(canvas.ClipRect);

end;

Если первая строка приведенного выше кода будет отсутствовать, при рисовании на компоненте Image изображение будет мерцать. Остальные строки необходимы, чтобы при запуске программы в редакторе присутствовало изображение.

9. Следующим шагом будет реализация возможности рисования линии черного цвета толщиной 1 пиксел. Рисование будет возможным как на созданных, так и на загруженных изображениях.

Для Image1 в обработчике OnMouseDown напишем:

image1.Canvas.MoveTo(x,y); //точка с координатами X,Y становится текущей точкой канвы.

Обработчик OnMouseMove Image1:

if ssleft in shift then //если нажата левая клавиша мышки

image1.Canvas.LineTo(x,y); //рисуется линия от текущей точки до точки с координатами X,Y и эта точка становится следующей текущей

10. Приступим к следующему этапу. Добавим редактору следующие функции: возможность рисования прямых линий, изменения толщины контура, а также возможность выбора цвета фона и контура. Разместим на форме дополнительные компоненты:

GroupBox1 (Capture = ‘Mode’), внутри которого размещены две кнопки:

SpeedButton1 (Capture=’Brush’, GroupIndex=1, Down=True) – кнопка для рисования в режиме «free hand»

SpeedButton2 (Capture =’Ruler’GroupIndex=1, Tag=1) - кнопка для рисования в режиме «прямой линии»

ColorGrid1 (свойство GridOrdering=go16x1 – ячейки расположены в один ряд)

SpiEdit1 (MaxValue=22, MinValue=1, Value=1, Increment=3).

Label1 (Capture=’Width’)

В свойстве Tag будет хранится номер режима рисования.

 

 

11. Напишем следующие обработчики:

OnChange для ColorGrid1:

image1.Canvas.Pen.Color:=colorgrid1.ForegroundColor; //цвет контура

image1.Canvas.Brush.Color:=colorgrid1.BackgroundColor; //цвет фона

OnChange для SpiEdit1:

image1.Canvas.Pen.Width:=spinedit1.Value;// задаем толщину линии

12. Теперь обеспечим возможность рисования во втором режиме – прямые линии.

OnClick для SpeedButton1:

image1.Tag:=(sender as tspeedbutton).Tag;

(sender as Tspeedbutton).Down:=true;

Для события OnClick SpeedButton2 выберем из списка SpeedButton1Click

Опишем глобальные переменные:

startPoint,MovePoint:tpoint;

А в секции Implementation (сразу после {$R *.dfm}) опишите следующую процедуру:

procedure drawfigure(p1,p2:tpoint; amode:TPenMode);

begin

with form1.Image1.Canvas do

begin

pen.Mode:=Amode;

MoveTo(p1.X,p1.Y);

lineto(p2.X,p2.Y);

end;

end;

13. Создадим следующие обработчики:

Image1 OnMouseUp:

if startpoint.X=10000 then exit;

if (image1.Tag=1) or

(image1.Tag=2) //это условие нам пригодится в будущем для рисования фигур

then drawfigure(startpoint,point(x,y),pmCopy);

Отредактируем метод Image1MouseMove следующим образом:

if ssleft in shift then

case image1.Tag of

0: image1.Canvas.LineTo(x,y);

1: begin

drawfigure(startpoint,movepoint,pmNotXor);

MovePoint:=Point(x,y);

DrawFigure(StartPoint,MovePoint,pmNotXor);

end;

end;

В метод Image1MouseDown добавьте:

startpoint:=point(x,y);

movePoint:=StartPoint;

Теперь рисование можно производить в двух режимах: в режиме «Brush» рисуются линии произвольной формы, а в новом режиме «Ruler» рисуются прямые линии.

14. Усложним на редактор. Добавим еще один инструмент – Рисование фигур

Добавим в GroupBox1 еще одну кнопку SpeedButton3 (Caption = ‘Figure’).

Параметры кнопки – GroupIndex=1, Tag=2

Разместим также в левом нижнем углу формы панель (Panel1) и поместим на нее компонент Shape1. Установите значения Width и Height для Shape1 на 4 пикселя меньше, чем соответствующие значения компонента Panel1. Разместите компонент Shape1 по центру панели.

Компонент Shape1 позволяет определить, как будет выглядеть нарисованная фигура. В других режимах рисования данный компонент позволяет визуально оценить текущие цвет и толщину линии. При щелчке левой клавиши мышки на компоненте-образце Shape1 изменяется тип фигуры (прямоугольник, прямоугольник с закругленными углами, эллипс) и происходит автоматический переход в режим «Figure». Щелчок правой клавиши по компоненту позволяет перейти в режим рисования фигур с равными измерениями (квадраты и т.п.).

 


15. Объявим еще две глобальные переменные: dx,dy:integer;

В раздел uses для Unit1 необходимо добавить модуль математических функций Math

Измените уже описанную нами процедуру DrawFigure следующим образом (добавить выделенные жирным строки):

with form1.Image1.Canvas do

begin

pen.Mode:=Amode;

case form1.Image1.tag of

1: begin

MoveTo(p1.X,p1.Y);

lineto(p2.X,p2.Y);

end;

2: begin

dx:=p2.X-p1.X;

dy:=p2.Y-p1.Y;

if abs(dx)>abs(dy) then dx:=abs(dy)*sign(dx) else dy:=abs(dx)*sign(dy);

case form1.shape1.Shape of

stRectangle:Rectangle(p1.X,p1.Y,p2.X,p2.Y);

stRoundRect:RoundRect(p1.X,p1.Y,p2.X,p2.Y,(p2.Y-p1.X) div 2,(p2.Y-p1.Y) div 2);

stEllipse: Ellipse(p1.X,p1.Y,p2.X,p2.Y);

stSquare:rectangle(p1.X,p1.Y,p1.X+dx,p1.Y+dy);

stRoundSquare:RoundRect(p1.X,p1.Y,p1.X+dx,p1.Y+dy,dx div 2, dy div 2);

stCircle:Ellipse(p1.X,p1.Y,p1.X+dx,p1.Y+dy);

end;

end;

end;

end;

В методе Image1MouseMove замените строку 1:begin на1,2:begin

В метод ColorGrid1Change добавьте:

shape1.Brush.Color:=colorgrid1.BackgroundColor;

shape1.Pen.Color:=ColorGrid1.ForegroundColor;

В метод SpinEdit1Change добавьте:

shape1.Pen.Width:=spinedit1.Value;

16. Создадим обработчик OnMouseDown для Shape1:

procedure TForm1.Shape1MouseDown(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

var i:integer;

begin

if ssLeft in Shift then

i:=(ord(shape1.Shape)+2) mod 6 else

if odd(ord(Shape1.Shape)) then

i:=ord(shape1.Shape)-1

else i:=ord(shape1.Shape)+1;

shape1.Shape:=tshapetype(i);

speedbutton3.Down:=true;

image1.Tag:=2;

end;

17. Реализуем функцию отмены предыдущей операции. Для этого объявим глобальную переменную oldbitmap:tbitmap;

Отредактируйте метод FormCreate следующим образом:

image1.Parent.DoubleBuffered:=true;

oldbitmap:=tbitmap.Create;

with image1 do

begin

picture.Bitmap.Width:=scrollbox1.Width;

picture.Bitmap.Height:=scrollbox1.Height;

canvas.FillRect(canvas.ClipRect);

oldbitmap.Width:=picture.Bitmap.Width;

oldbitmap.Height:=picture.Bitmap.Height;

end;

end;

Создадим обработчик OnDestroy для Form1:

oldbitmap.Free;

Установим свойству KeyPreview формы значение true и напишем обработчик OnKeyPress для формы:

if key=#27 then

with image1.Canvas do

copyrect(cliprect,oldbitmap.Canvas,cliprect);

Теперь любую графическую операцию можно отменить сразу после ее выполнения, нажав клавишу Esc.

18. Добавим нашему редактору еще несколько функциональных возможностей. Реализуем возможность использования дополнительных цветов.

Разместим на форме компоненты StaticText1 (Caption=’FG’), StaticText2 (Caption=’BG’) (панель Additional) и ColorDialog1. Для компонентов StaticText1 и StaticText2 зададим следующие свойства:

Alignment=taCenter; AutoSize=False; BorderStyle=sbsSunken; Font.Color = cllnactiveCaption.

В секцию imlementation добавьте следующую процедуру:

procedure NewColor (sender:TObject; Acolor:TColor);

begin

with Form1 do

begin

if sender = StaticText1 then

Colorgrid1.ForegroundIndex:=-1 else

Colorgrid1.BackgroundIndex:=-1; // скрытие подписей FG и BG на компоненте ColorGrid1

(sender as TStaticText).Color:=AColor;

(sender as TStaticText).Font.Color:=AColor xor $FFFFFF; //цвет текста на компонентах StaticText будет инверсным к фону компонента

ColorGrid1Change(Sender);

end;

end;

19. Напишем обработчик OnMouseDown для StaticText1:

with ColorDialog1 do

begin

if Sender=StaticText1 then

Color:=Shape1.Pen.Color

else Color:=Shape1.Brush.Color;

if execute then //вызов диалогового окна ColorDialog1, если оно было закрыто кнопкой «ОК», Execute=true

NewColor(sender,color);

end;

Для OnMouseDown StaticText2 выберем StaticText1MouseDown

Обработчик OnChange для Colorgrid1 изменим следующим образом:

with colorgrid1 do

begin

if ForegroundIndex <>-1 then

begin

shape1.Pen.Color:=ForegroundColor;

StaticText1.Color:=clBtnFace;

StaticText1.Font.Color:=clInactiveCaption;

end

else

shape1.Pen.Color:=StaticText1.Color;

image1.Canvas.Pen.Color:=shape1.Pen.Color;

if BackGroundIndex<>-1 then

begin

StaticText2.Color:=clBtnFace;

StaticText2.Font.Color:=clInactiveCaption;

end;

if BackGroundIndex<>-1 then

Shape1.Brush.Color:=BackgroundColor

else shape1.Brush.Color:=StaticText2.Color;

image1.Canvas.Brush.Color:=shape1.Brush.Color;

end;

Для выбора цвета линии или цвета фона, не входящего в палитру ColorGrid1, нужно щелкнуть мышкой по компонентам StaticText1 или StaticText2 соответственно, в появившемся диалоговом окне «Цвет» указать новый цвет и нажать ОК. При этом компонент StaticText окрасится в соответствующий текст, а метка «FG»(«BG») из палитры ColorGrid1 исчезнет.

20. Реализуем задание цветов при помощи «пипетки». Внесем изменения в обработчик OnMouseDown для Image1:

with image1.Canvas do

begin

oldbitmap.Canvas.CopyRect(cliprect,image1.Canvas,cliprect);

if ssAlt in Shift then

case Button of

mbLeft:NewColor(Statictext1,Pixels[x,y]);

mbRight:NewColor(StaticText2,Pixels[x,y]);

end;

end;

image1.Canvas.MoveTo(x,y);

startpoint:=point(x,y);

movePoint:=StartPoint;

Теперь новый цвет линии и фона можно получить непосредственно из изображения, щелкнув соответственной левой или правой клавишей мышки в нужном месте при нажатой клавише Alt.

21. Разместим на форме дополнительные компоненты.

 

 

Компоненты SpeedButton4 (Cuption=’Roller’, GroupIndex=1, Tag=3), SpeedButton5 (Cuption=’Text’, GroupIndex=1, Tag=4), Label2 (Caption=’Text’), Label3 (Caption=’Style’), Button5 (Caption=’Font’), Edit1 (Text=’’), FontDialog1 (Options.fdEffects=false – отключение возможности настройки цвета шрифта, а также выбора режима подчеркивания и перечеркивания текста), ComboBox1 и ComboBox2 (Style=csOwnerDeawFixed, Text=’’, ItemIndex=0).

Для кнопок SpeedButton событие OnClick определите как SpeedButton1Click.

22. Четвертым режимом рисования будет «Валик» (Roller). Этот режим позволяет заливать текущим цветом фона области, ограниченные линиями других цветов. Заливка производится при щелчке мышью внутри нужной области.

Внесем изменение в метод Image1MouseDown:

if ssAlt in Shift then

case Button of

mbLeft:NewColor(Statictext1,Pixels[x,y]);

mbRight:NewColor(StaticText2,Pixels[x,y]);

end

else

if image1.Tag=3 then

FloodFill(x,y,pixels[x,y],fsSurface)

23. Пятый режим – добавление в рисунок текста. В метод Image1MouseDown добавим:

if image1.Tag=3 then

FloodFill(x,y,pixels[x,y],fsSurface)

else if image1.tag=4 then TextOut(x,y,edit1.Text);

Создадим обработчик OnEnter для Edit1:

SpeedButton5.Down:=true;

Image1.Tag:=4;

В метод ColorGrid1Change добавьте операторы:

image1.Canvas.Pen.Color:=shape1.Pen.Color;

image1.Canvas.Font.Color:=shape1.Pen.Color;

Новый режим позволяет помещать на изображение текст, содержащийся в поле ввода Edit1. Текст вставляется при нажатии левой кнопки мыши, место нажатия определяет начальную позицию текста. Цвет текста совпадает с текущим фоном.

24. Нажатие кнопки Font позволяет изменить шрифт вставляемой надписи.

Для кнопки Button5 напишем обработчик OnClick

with FontDialog1 do

begin

font:=Image1.Canvas.Font;

if execute then

image1.Canvas.Font:=font;

end;

25. Занесем в свойство Items ComboBox1 6 строк, содержащих числа 0,1,2,3,4,5. В компонент ComboBox2 занесем 8 строк (0,1,2,3,4,5,6,7).

Опишем OnDrawItem для ComboBox1:

with comboBox1.Canvas,Rect do

begin

brush.Color:=clWhite;

Pen.Color:=clBlack;

Pen.Style:=TPenStyle(StrToInt(Combobox1.Items[index]));

MoveTo(Left,(top+Bottom) div 2);

LineTo(Right,(top+Bottom) div 2);

end;

Создадим для ComboBox1 обработчик OnChange:

with ComboBox1, Shape1.pen do

begin

Style:=TPenStyle(StrToInt(Items[ItemIndex]));

Image1.Canvas.Pen.Style:=Style;

ColorGrid1Change(Sender);

end;

Аналогично поступим с ComboBox2:

OnDrawItem для ComboBox2:

with ComboBox2.Canvas do

begin

Brush.Color:=clGray;

Brush.Style:=TBrushStyle(StrToInt(ComboBox2.Items[Index]));

FillRect(Rect);

end;

ComboBox1 событие OnChange:

with ComboBox2, Shape1.Brush do

begin

Style:=TBrushStyle(StrToInt(Items[ItemIndex]));

Image1.Canvas.Brush.Style:=Style;

Button4.Enabled:=Style<> bsClear;

ColorGrid1Change(Sender);

end;

В результате мы получим два выпадающих списка, которые позволяют выбрать все возможные стили рисования линии и заливки фона. Варианты стилей отображаются в выпадающих списках в графическом виде.

Результатом выполнения данной лабораторной работы являются созданный согласно заданию программный продукт. Выполненное задание должно быть предъявлено преподавателю в электронном виде. В ходе защиты лабораторной работы студент должен продемонстрировать свои навыки работы с изученными компонентами и методами проектирования интерфейса пользователя.

Размещено на Allbest.ru

 


Поделиться с друзьями:

Архитектура электронного правительства: Единая архитектура – это методологический подход при создании системы управления государства, который строится...

Эмиссия газов от очистных сооружений канализации: В последние годы внимание мирового сообщества сосредоточено на экологических проблемах...

Археология об основании Рима: Новые раскопки проясняют и такой острый дискуссионный вопрос, как дата самого возникновения Рима...

Особенности сооружения опор в сложных условиях: Сооружение ВЛ в районах с суровыми климатическими и тяжелыми геологическими условиями...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.174 с.