Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

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




Например, оператор

ImageI.Canvas.Draw(10,10,Bitmapl);

рисует на канве компонента Imagel изображение из компонента Bitmap1 в область с координатами левого верхнего угла (10, 10).

Еще один метод рисования — DrawFocusRect. Этот метод рисует изображение прямоугольника в виде, используемом для отображения рамки фокуса, операцией XOR. Функция DrawFocusRect объявлена следующим образом:

procedure DrawFocusRect(const Rect: TRect);

где Rect — прямоугольная область. Поскольку при рисовании используется операция XOR, то повторный вызов этого метода с тем же значением Rect удаляет изображение прямоугольника.

 

 

Теперь мы рассмотрели большинство вопросов, связанных с графикой. Можно вернуться к созданному нами ранее собственному графическому редактору и попробовать его усовершенствовать. Редактор этот чисто демонстрационный и поэтому в нем нет многого, что должно быть в настоящем графическом редакторе. К тому же и тот инстру­ментарий, который в нем имеется, надо бы было реализовать компактнее и с боль­шей надежностью. Но в данном случае, как и во всех демонстрационных приме­рах, функциональность принесена в жертву простоте и наглядности кода.

Тем не менее мы не будем подробно анализировать текст этого приложения. Рассмотрим только основные приемы, которые использованы при создании раз­личных инструментов. А общую логику работы вы можете придумать сами или по­заимствовать ее из примера.

Приложение выполняет следующие функции:

• Установка основного и дополнительного цветов. Щелчок на панели цветов ле­вой кнопкой мыши устанавливает основной цвет, а щелчок правой кнопкой — вспомогательный.

• Кисть — кнопка SBBrush. Закрашивает замкнутую область, ограниченную цветом того пикселя, который указан щелчком мыши. При щелчке левой кнопкой закрашивание производится основным цветом, при щелчке правой кнопкой — вспомогательным.

• Индикация цвета — кнопка SBColor. В этом режиме вы можете указать кур­сором мыши любой пиксель на изображении и, щелкнув левой кнопкой, уста­новить цвет этого пикселя как основной, а щелкнув правой кнопкой, устано­вить его как вспомогательный цвет.

• Карандаш — кнопка SBPen. В этом режиме вы можете рисовать произволь­ную кривую основным цветом.

• Выделение фрагмента — кнопка SBRect. Фрагмент выделяется точечной рам­кой. Выделенный фрагмент можно в дальнейшем перетащить мышью на дру­гое место. Если в процессе перетаскивания нажата клавиша Ctrl, то произво­дится копирование фрагмента, в противном случае — вырезание, при котором область начального размещения фрагмента закрашивается вспомогательным цветом. Выделенный фрагмент может быть также скопирован или вырезан в буфер обмена Clipboard соответствующими командами меню.

• Стирание изображения (ластик) —кнопка SBErase. Перемещение ластика за­крашивает область под ним во вспомогательный цвет.

• Рисование прямоугольника — кнопка SBRectang. Рисуется прямоугольная рамка основным цветом.

• Рисование заполненного прямоугольника — кнопка SBFillRec. Рисуется пря­моугольная рамка основным цветом и прямоугольник внутри закрашивается вспомогательным цветом.

• Рисование прямой линии — кнопка SBLine. Рисуется прямая линия основ­ным цветом.

• Открытие графического файла — команда Файл | Открыть.

• Сохранение изображения в графическом файле — команда Файл | Сохранить как....

• Отмена операций, выполненных последним использованным инструментом — команда Правка | Отменить.

• Копирование или вырезание выделенного фрагмента изображения в буфер об­мена Clipboard — команды Правка | Копировать или Правка | Вырезать.

• Вставка графического изображения типа битовой матрицы из буфера обмена Clipboard — команда Правка | Вставить.

Начнем с рассмотрения функции выделения фрагмента. Она осуществляется методом DrawFocusRect. В этом режиме при событии OnMouseDown холста компонента Image3, выполняются операторы:

// запоминание начального положения курсора мыши ХО:=Х;,YO:=Y;

// формирование начального положения области фрагмента R.TopLeft!= Point(X,Y); R.BottomRight:= Point(X,Y); // рисование рамки ImageS.Canvas.DrawFocusRect(R); RBegin:= true;

Эти операторы запоминают координаты мыши X и Y в переменных ХО и YO, задают начальные координаты прямоугольной области — переменной R типа TRect и рисуют рамку (пока нулевого размера) методом DrawFocusRect. Устанав­ливается также флаг начала выделения фрагмента — переменная RBegin.

При событии OnMouseMove компонента Image3, если установлен флаг RBe­gin, выполняются операторы:

// стирание прежней рамки Image3.Canvas.DrawFocusRect(R);

// формирование области R if ХО < X

then begin R.Left:= ХО;

R.Right:= X end else begin R.Left:= X; R.Right:= XO end; if YO < Y

then begin R.Top:= УО;

R.Bottom:= Y end

else begin R.Top:= Y;

R.Bottom:= YO end;

// рисование новой рамки Image3.Canvas.DrawFocusRect(R);

Первый из этих операторов стирает прежнее изображение рамки (напомним, что метод DrawrFocusRect рисует рамку с помощью операции XOR). Два следую­щих оператора формируют новую область R из начальных координат (ХО, YO) и те­кущих координат курсора (X, Y). Дело в том, что область, передаваемая в функ­цию DrawFocusRect, должна быть сформирована «правильно» — значение R.Left должно быть меньше R.Right, a R.Top — меньше R.Bottom. А поскольку пользо­ватель может перемещать курсор в любом направлении и соотношение координат (ХО, YO) и (X, Y) может быть любым, требуется упорядочивание координат.

Последний оператор рисует рамку в новом положении.

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

with Image3.Canvas do begin

// стирание,.прежней рамки DrawFocusReet(R);

// установка флага перетаскивания

RDrag:= true;

// запоминание начального положения курсора мыши

ХО:= X; У0:= Y;

//запоминание начального положения перетаскиваемого фрагмента

RO.TopLeft:= R.TopLeft; RO.BottomRight:= R.BottomRight;

// запоминание изображения

BitMap. Assign'(Image3.Picture);

// установка, цвета кисти-Brush. Color:= Image2.Canvas.Brush.Color;

end;

Первый оператор стирает рамку. Второй— устанавливает флаг перетаскива­ния — переменную RDrag. Два следующих оператора запоминают начальное поло­жение перетаскиваемого фрагмента в переменной RO типа TRect. Следующий опе­ратор запоминает методом Assign изображение в момент начала перетаскивания в переменной BitMap. Это необходимо, чтобы в процессе перетаскивания можно было восстанавливать испорченные места изображения и чтобы при желании по­льзователя можно было в дальнейшем отменить результат перетаскивания. По­следний оператор задает цвет кисти равным вспомогательному цвету, хранящему­ся в компоненте Image2.

При событии OnMouseMove компонента Image3, если установлен флаг RDrag, выполняются операторы:

// восстановление изображения под перетаскиваемым фрагментом.

CopyRect (R,BitMap.Canvas,R);

// если не нажата клавиша Ctrl - стирание изображения в .RO

if not (ssCtrl in Shift) then FillRect (RO);

// формирование нового положения фрагмента

R.Left:= R.Left + X - ХО;

R.Right:= R.Right + X - XO;

R.Top:= R.Top + Y - YO;

R.Bottom:= R.Bottom + Y - YO;

// запоминание положения курсора мыши

ХО:= X;

YO:= Y;

// рисование фрагмента в новом положении

CopyRect(R,BitMap.Canvas,R0);

// рисование рамки

DrawFocusRect (R);

Первый оператор восстанавливает изображение под перетаскиваемым фраг­ментом в его прежней позиции (т.е. стирает фрагмент), копируя соответствую­щую область методом CopyRect из компонента BitMap. Далее, если не нажата кла­виша Ctrl, то очищается область начального размещения фрагмента (осуществляет­ся вырезание) методом FillRect. Затем запоминаются новые координаты курсора и новое положение фрагмента, после чего фрагмент и его рамка рисуются в новом положении.

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

Режимы рисования заполненного и не заполненного прямоугольников проще. Начало этих режимов по событию OnMouseDown и их продолжение по событиям OnMouseMove не отличаются от рассмотренного ранее режима выделения фраг­мента. Отличие только в том, что при завершении формирования пользователем прямоугольной рамки, т.е. при событии OnMouseUp, надо в данном случае нарисо­вать прямоугольник. Рисование заполненного прямоугольника осуществляется операторами:

with Image3.Canvas do begin;

Brush.Color:= Image2.Canvas.Brush.Color;

Pen.Color:= Imagel.Canvas.Brush.Color;

Rectangle(R.Left,R.Top,R.Right,R.Bottom); end;

Они задают цвета кисти и пера и рисуют прямоугольник методом Rectangle. Рисование не закрашенного прямоугольника осуществляется операторами:

with Image3.Canvas do begin

Brush.Color:= Imagel.Canvas.Brush.Color;

FrameRect(R); end;

Обратите внимание, что равным основному цвету задается цвет кисти, а не пера, поскольку метод FrameRect рисует цветом кисти.

Рисование прямой линии осуществляется следующим образом. Начало рисо­вания по событию OnMouseDown сводится к операторам:

ХО:= X;

YO:= Y;

XI:= X;

Y1:= Y;

Image3.Canvas.Pen.Color:= Imagel.Canvas.Brush.Color;

Image3.Canvas.Pen.Mode:= pmNotXor;

Они запоминают положение курсора в двух наборах переменных: (ХО, YO) и (XI, Y1). Зачем нужны два набора — будет сказано позднее. Затем устанавливает­ся цвет пера и режим pmNotXor, который позволит при движении мыши стирать изображение линии.

При событиях OnMouseMove работают следующие операторы:

with Image3.Canvas do begin // стирание прежней линии

MoveTo(ХО,YO);

LineTo(XI,Yl); // рисование новой линии

MoveTo(ХО,YO);

LineTo(X,Y); // запоминание новых координат конца линии

XI:= X;

Yl:= Y; end;

В этих операциях сначала парой методов MoveTo и LineTo стирается линия в прежнем положении, а затем такой же парой методов рисуется новая линия. По­сле этого запоминаются новые координаты конца линии.

Попробуем разобраться, зачем все так сложно. Ведь казалось бы, что достаточ­но всего двух операторов:

LineTo (XO,YO); LineTo(X,Y);

Первый из них сотрет прежнюю линию, поскольку текущая позиция пера по­сле рисования этой прежней линии соответствовала концу линии (тем координа­там, которые мы храним в переменных XI, Y1). А второй оператор нарисует новую линию. И не надо хранить никаких координат.

Так просто нельзя сделать из-за одной тонкости: метод LineTo рисует линию, начинающуюся в текущей позиции пера и заканчивающуюся в указанной точке, исключая эту конечную точку. Поэтому, если выполнить в режиме pmNotXor приведенные выше операторы, то первый из них сотрет прежнюю линию, но оста­вит нестертой точку с координатами (X0, Y0) и, кроме того, нарисует точку в быв­шей позиции курсора, поскольку она, как конечная, была исключена при рисова­нии предыдущей линии. Таким образом, на концах линии останется «грязь» в виде концевых точек, которая и будет тянуться за перемещающимся курсором мыши.

Заключительные операции при событии OnMouseUp аналогичны рассмотрен­ным выше, но дополняются переводом пера в режим рmСору, при котором рисует­ся окончательная линия:

with Imaige3.Canvas do begin // стирание прежней линии

MoveTo(XO,YO);

LineTo(XI,Yl); // рисование новой линии

Pen.Mode:= pmCopy;

MoveTo(XO,YO);

LineTo(X,Y); end;

Теперь рассмотрим инструмент Перо, позволяющий рисовать произвольные линии. Казалось бы естественной реализацией этого инструмента был бы оператор

Image3.Canvas.Pixels[X,Y]:= Imagel.Canvas.Brush.Color;

который окрашивает пиксель под курсором в основной цвет. Однако попробуйте так реализовать Перо и ничего хорошего не увидите. Курсор мыши перемещается быстро и события OnMouseMove происходят вовсе не при перемещении на сосед­ний пиксель. Линию, оставляемую курсором, следует рисовать тоже методом LineTo, поместив в обработчик события OnMouseMove оператор

Image3.Canvas.LineTo(X, Y).

Коротко перечислим оставшееся. Ластик реализуется методом FillRect, очищаю­щим изображение под его рамкой. Кисть, отмена команд и загрузка внешнего фай­ла. Сохранение файла осуществляется с использо­ванием компонента типа SavePictureDialog.

Изображение с холста сохраняется в компоненте BitMap, из которого методом SaveToFile записывается в выбранный пользователем файл.

Команды меню Копировать и Вырезать осуществляются процедурой

procedure TForml.MGopyClick(Sender: TObject); var BMCopy: TBitMap;

begin

// стирание рамки

Image3.Canvas.DrawFocusRect(R); // создание временного объекта ВМСору

ВМСору:= BitMap.Create;

ВМСору.Width:= R.Right - R.Left;

ВМСору.Height:= R.Bottom - R.Top;

try

// копирование фрагмента в BM Сору

ВМСору.Canvas.Соругееt(Rect(0,0,ВМСору.Width,

ВМСору.Height)

Image3.Canvas,R); // восстановление рамки

Images.Canvas.DrawFocusRect (R); // копирование в Clipboard

ClipBoard.Assign(ВМСору); if

(Sender as TMenuItem).Name:= 'MCut'

then begin // вырезание

Image3.Canvas.Brush.Color:=clWhite;

Image3.Canvas.FillRect(R);

end; finally // освобождение памяти

ВМСору.Free; end; end;

Копированию или вырезанию подлежит ранее выделенный пользователем объект, местоположение и размеры которого определяются переменной R. Поэто­му сначала создается временный объект типа TBitMap, в который переносится ко­пируемый фрагмент. Затем этот объект копируется в Clipboard. Благодаря разделу finally память освобождается от временного объекта при любом исходе копирова­ния: удачном или аварийном.

Аналогично реализуется команда Вставить, копирующая изображение из буфе­ра обмена Clipboard:

procedure TForml.MPasteClick(Sender: TObject); var ВМСору:TBitMap; begin

ВМСору:=BitMap.Create;

try

try

ВМСору.LoadFromClipBoardFormat(cf_BitMap,

ClipBoard.GetAsHandle(cf_Bitmap),0);

Image3.Canvas.CopyRect(Rect(0,0,ВМСору.Width, ВМСору.Height),

ВМСору.Canvas,Rect(0,0,ВМСору.Width,ВМСору.Height)):

finally

ВМСору.Free; end; except

On EInvalidGraphic do ShowMessage(Ошибочный формат графики); end;

end;

Чтение из Clipboard осуществляется методом LoadFromClipBoardFormat. Предусмотрен перехват исключения EInvalidGraphic, если в Clipboard содержится не битовая матрица.

Попро­буйте также усовершенствовать редактор, добавив в него, например, выбор шири­ны линий, рисование эллипсов и т.д.

 




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


Дата добавления: 2015-03-29; Просмотров: 502; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.006 сек.