Создание приложения наподобие графического редактора

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

Приложение должно узнавать, какую кнопку нажал пользователь, и переходить в режим рисования данного объекта. Для этого вы можете сопоставить с каждым типом фигуры целое число, но в этом случае вам придется помнить, что обозначает каждое число. Если вы позволите пользователю создавать множество фигур, то это будет довольно трудно.

Однако все это можно значительно упростить, если вы сопоставите имена-константы каждому числу. Кроме того, вы можете прибегнуть к применe-нию перечисляемого типа.

Для объявления перечисляемого типа используйте слово Тyре. Например, нижеприведенный код объявляет перечисляемый тип, содержащий все типы фигур, которые приложение позволяет рисовать пользователю:

type
TDrawangTool = (dtLxne, dtRectangle, dtEllipse, dtRoundRect);

По соглашению, идентификатор типа (в нашем случае — это TDrawmgTool) начинается с буквы T, а группа перечисляемых констант начинается с двух-буквенного префикса (в нашем случае — букв dt).

Это объявление эквивалентно объявлению группы констант:

const
dtLine = 0;
dtRectangle = 1;
dtEllipse = 2;
dtRoundRect = 3;

Главное отличие объявления группы констант и перечисляемого типа заключается в том, что в случае объявления типа вы присваиваете константам не только значение, но и новый тип, который позволяет языку Object Pascal проверять соответствие типов и предотвращать возможные ошибки. Переменная, имеющая тип TDrawingTool, может иметь значение только из перечисленных (dtLine ... dtRoundRect). Любая попытка присвоения переменной других чисел (не входящих в диапазон от 0 до 3) вызовет ошибку компиляции.

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

Листинг 13.13.Объявление типа и переменных

type
TDrawingTool = (dtLine, dtRectangle, dtEllipse, dtRoundRect);
TForm1 = class(TForm)
. . . { объявление методов }
public
Drawing: Boolean;
Origin, MovePt: TPoint;
DrawingTool: TDrawingTool; { переменная, которая будет содержать текущий
инструмент }
end;

Расположим на панели инструментов четыре кнопки SpeedButton, каждая из которых будет означать линию, прямоугольник, эллипс или прямоугольник со скругленными углами. Теперь нужно для каждой кнопки написать обработчик события OnClick, в котором необходимо присвоить соответствующее значение переменной DrawingTool (листинг 13.14).

Листинг 13.14. Обработчики нажатия кнопок

procedure TForm1.LineButtonClick{Sender: TObject); { Кнопка линии } 
begin
DrawingTool := dtLine; end;
procedure TForm1.RectangleButtonClick(Sender: TObject); { Кнопка
прямоугольника } begin
DrawingTool := dtRectangle; end; procedure TForm1.EllipseButtonClick (Sender: TObject); { Кнопка эллипса } begin
DrawingTool := dtEllipse; end;
procedure TForm1.RoundedRectButtonClick(Sender: TObject}; { Кнопка
прямоугольника со скругленными углами } begin
DrawingTool := dtKoundRect; end;

Теперь нам осталось написать лишь обработчики событий движения мыши (OnMouseMove) и отпускания левой кнопки мыши (OnMouseUр). Эти обработчики представлены в листингах 13.15 и 13.16.

Листинг 13.15.Обработчик события OnMouseup

procedure TForm1. FormMouseUp (Sender: TObject; Button TMouseButton; Shift: 
TShiftState; 
X ,Y: Integer); 
begin
case DrawingTool of dtLine: begin
Canvas.MoveTo(Origin.X, Origin. Y); Canvas.LineTo(X, Y) end;
dtRectangle: Canvas.Rectangle{Origin.X, Origin.Y, X, Y); dtEllipse: Canvas.Ellipse(Origin.X, Origin.Y, X, Y); dtRoundRect: Canvas.RoundRect(Origin.X, Origin.Y, X, Y, (Origin.X - X} div 2, (Origin.Y - Y) div 2); end;
Drawing := False; end;

Листинг 13.16.Обработчик события OnMouseMove

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: 
Integer);
begin
if Drawing then
begin
Canvas.Pen.Mode := pmNotXor; case DrawingTool of dtLine: begin
Canvas.MoveTo(Origin.X, Origin.Y);
Canvas.LineTo(MovePt.X, MovePt.Y);
Canvas.MoveTo(Origin.X, Origin.Y);
Canvas.LineTo(X, Y); end; dtRectangle: begin
Canvas.Rectangle(Origin.X, Origin.Y, MovePt.X, MovePt.Y);
Canvas.Rectangle(Origin.X, Origin.Y, X, Y); end;
dtEllipse: begin
Canvas.Ellipse(Origin.X, Origin.Y, X, Y);
Canvas.Ellipse(Origin.X, Origin.Y, X, Y); end;
dtRoundRect: begin
Canvas.RoundRect(Origin.X, Origin.Y, X, Y, (Origin.X - X) div 2, (Origin.Y - Y) div 2);
Canvas.RoundRect(Origin.X, Origin.Y, X, Y,
(Origin.X - X) div 2, (Origin.Y - Y) div 2); end; end;
MovePt := Point(X, Y); end;
Canvas.Pen.Mode := pmCopy; end;
Hosted by uCoz