КАТЕГОРИИ: Архитектура-(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, если установлен флаг RBegin, выполняются операторы: // стирание прежней рамки 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; Просмотров: 522; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |