Объект TCanvas | |
  | |
В этом обзоре � дам описание объекта TCanvas, изложу его смысл и внутренний мир, а также методы его использовани�. | |
  | |
Что такое TCanvas | |
TCanvas это объект, который предназначен дл� рисовани� различными графическими примитивами в окнах. Этот объект содержит набор методов дл� рисовани�, а также набор свойств, используемых дл� них. Фактически, объект TCanvas �вл�етс� дополненным вариантом графического контекста Windows. Каждому окну выдел�етс� область дл� рисовани� (поверхность), котора� соответствует размеру окна, на которой можно рисовать с помощью методов объекта TCanvas. Чтобы глубже пон�ть смысл этого объекта нужно окунутьс� в мир графики Windows на уровне Windows API. Дело в том, что дл� того чтобы не путатьс�, Windows выдел�ет дл� каждого окна специальную логическую область и присваивает ей название. После этого разработчик использу� это название рисует именно в этой области. Если он направл�ет графический вывод в область с другим названием, то рисование происходит уже в другом окне. Эта область получила название графического контекста устройства. Контексты служат дл� логического разделени� всех графических операций Windows, и если сказать точнее, чтобы окна не мешали друг другу. Windows управл�ет всеми контекстами и берет на себ� все операции по отсечению вывода, который выходит за пределы окна и вывода, который закрыт другим окном. Программиру� на Win32 API нужно вручную определ�ть контексты дл� каждого окна. В данном случае под окном подразумеваетс� любой элемент управлени� Windows - кнопка, поле ввода и т.д. Определив контекст, автоматически организуетс� область котора� накладываетс� на окно (его рабоча� область) и она соответствует размерам окна. Сначала эта область пуста, а затем, с помошью функций GDI вы в любой момент можете направл�ть вывод в это окно указыва� в каждой из них название контекста, который предназначен дл� этого окна. Каждый контекст содержит также р�д параметров, которые используютс� дл� рисовани�. Допустим линии рисуютс� с помощью пера, которое в Win32 API имеет тип HPEN, соответственно нужно устанавливать его аттрибуты такие как цвет, толщина и т.д. Дл� заполнени� фигур используетс� кисть, котора� имеет тип HBRUSH. Чтобы заполнить фигуру нужно определить и этот объект, т.е. указать тип кисти, ее цвет и т.д. �о же самое касаетс� и шрифта дл� текста (HFONT). Все эти объекты создаютс� отдельно и затем в нужный момент помещаютс� в соответствующие свойства контекста. Дл� разработки окна с собственным контекстом на Win32 API уходит много времени и соответственно строк кода. Поэтому Delphi, как среда, котора� облегчает разработчику жизнь представл�ет немного иной подход к рисованию, хот� он и базируетс� на Win32 API. Объект TCanvas был создан дл� того чтобы объеденить в единое целое контекст, его свойства и функции GDI дл� рисовани� в контексте. �еперь если вы рисуете в этом объекте с помощью функций рисовани�, вы можете не заботитс� о том, что рисование будет выведено не в тот контекст или не в то окно. | |
  | |
Как TCanvas используетс� в Delphi | |
Как известно все в Delphi состоит из компонентов. Хот� и эти компоненты имеют таких хитрых предков как TPersistent, TComponent и TControl, все они �вл�ютс� окнами. Соответственно у каждого из них может быть контекст, на котором можно рисовать. Однако дл� логических и стратегических целей разработчики Delphi НЕ позвол�ют рисовать в абсолютно каждом компоненте. Допустим нельз� вз�ть и нарисовать что-нибудь на кнопке типа TButton или в поле редактировани�, типа TEdit. Однако это не проблема, так как существует целый класс потомков и предков, позвол�ющих организовывать эти эффекты. Я сейчас не буду заостр�ть внимание на каждом из них. По�сню только общие принципы. У каждого компонента, в котором можно что-либо рисовать есть свойство Canvas. Именно оно и �вл�етс� собственным TCanvas-ом данного компонента. Он и используетс� дл� вывода в данный компонент. �акже у каждого компонента есть обработчик OnPaint, который вызываетс� каждый раз когда на внешний вид формы что-то повли�ло, т.е. ее перекрыло что-то, или ее свернули. Поэтому все рисование стоит выполн�ть в этом методе. Вот простейший пример того, как можно нарисовать что-то в форме.
procedure Form1.FormPaint(Sender: TObject); begin Canvas.MoveTo(10,10); Canvas.LineTo(10,20); Canvas.LineTo(20,20); Canvas.LineTo(20,10); Canvas.LineTo(10,10); end; Данный пример рисует в форме пр�моугольник (квадрат 10x10) использу� методы рисовани� объекта Canvas. Вы заметили что процедура называетс� FormPaint, хот� � ранее говорил, что она называетс� OnPaint. Дело в том что между событием и процедурой реакции на событие есть определенна� разница. Дело в том, что каждому событию присваиваетс� определенна� процедура. Событи� нужно искать на вкладке Events ObjectInspector-а, найдите там событие OnPaint, дважды щелкните на него и вы окажетесь в процедуре FormPaint, если это будет форма. Итак, вы увидели, как быстро теперь можно рисовать в форме. Это значительно быстрее чем делать вызовы Win32 API. (хот� дл� полного эффекта их все-таки делать надо,однако об этом далее позже....). Выполнив этот пример мы видим пр�моугольник нарисованный тонкой линией черного цвета. Неужели этого нельз� изменить, подумаете вы? Конечно же можно и об этом далее. | |
  | Аттрибуты TCanvas |
Объект TCanvas содержит набор свойств, определ�ющих как будут рисоватьс� линии, как будут заполн�тьс� фигуры и как будет изображатьс� текст. Соответсвенно они называютс� Pen, Brush и Font. Линии рисуют пером, которое определ�етс� свойством Pen. Свойство Pen �вл�етс� объектом типа TPen, который содержит соответствующие методы и свойства, определ�ющие аттрибуты линии. Заполн�ют фигуры кистью, котора� определ�етс� свойством Brush, которое �вл�етс� объектом TBrush и содержит методы и свойства дл� определени� аттрибутов кисти. �екст рисуетс� с использованием указанного шрифта, который определ�етс� свойством Font, которое �вл�етс� объектом TFont и содержит все необходимые аттрибуты шрифта. После того как вы определили любой из этих объектов, он будет распростран�тьс� на все дальнейшие функции рисовани�, дл� которых он требуетс� до тех пор, пока вы не изменили его свойства. Это значит, что если вы, например, установили перо в красный цвет и нарисовали красную линию, то дл� того чтобы нарисовать синюю линию, вам нужно снова изменить соответствующее свойство объекта Pen. Далее будут подробнее рассмотрены эти объекты. | |
  | |
TPen | |
TPen �вл�етс� объектом, который служит дл� создани� перьев, с помощью которых рисуютс� линии. Св�зь этого объекта с TCanvas осуществл�етс� с помощью свойства Pen, которое используетс� каждым графическим методом TCanvas, который рисует линии. Объект TPen определ�ет перо как объект состо�щий из:
Стил� линии: Style Стиль линии определ�ет, будет ли лини� сплошной, штриховой, штрихпунктирной и т.д. Вы можете установить это свойство в одно из следующих значений:
psSolid - сплошна� лини� �олщина линии указываетс� в виде числа. �олщина измер�етс� в пикселах. Цвет линии может указыватьс� в виде специального шестнадцатеричного 4-х байтового значени�, где определены концентраци� красной, зеленой и синей составл�ющих. Вот как выгл�дит шаблон: $00000000 Первые два нул� зарезервированы, вторые два разр�да используютс� как шестнадцатеричное представление концентрации зеленого цвета, вторые два разр�да дл� синей составл�ющей, и третие два разр�да дл� красной. В дес�тичном представлении концентраци� выражаетс� в диапазоне от 0 до 255, а в шестнадцатеричном, соответственно: от 00 до FF. Комбиниру� эти три параметра в разных концентраци�х можно добитьс� любого цвета из 16-милионной гаммы. Вот несколько примеров:
$00FF0000 - зеленый Можно, конечно, сидеть и набирать эти комбинации каждый раз, чтобы изменить цвет. Дл� создани� каких-либо красивых пейзажей и натюрмортов это даже необходимо. Однако если нужно просто нарисовать три линии красного, голубого и зеленого цвета, то пользу�сь этим методом можно потратить значительно больше времени чем можно было бы потратить. Дл� того, чтобы выполн�ть примитивные рисунки проще, был создан набор удобочитаемых констант, которые определ�ют часто-иснользуемые цвета. Пользу�сь ими, можно не набирать эти цвета с помощью этого 4-х байтового значени�:
clLime - светло-зеленый Кому проще так, пользуйтесь, хот� это то же самое. Пример установки пера:
| |
  | |
TBrush | |
Кисть используетс� дл� заполнени� фигур и содержит следующие параметры:
Стиль(узор) - Style Это значит, что любую фигуру можно заполнить либо цветом, либо узором с цветом, либо изображением из BMP-файла. Узоры бывают следующие:
bsSolid - сплошное заполнение Цвет указываетс� также как и у пера, поэтому описывать второй раз не буду. Картинка �вл�етс� объектом TBitmap, который содержит много интересных свойств и методов. Вообще использование битовых карт это очень обширна� тема котора� глубоко уходит в Win32 API и этому посв�щена отдельна� стать�. Здесь � не буду описывать все тонкости этого объекта. Дл� использовани� этого объекта в качестве кисти важно знать следующее: можно загрузить картинку из файла в переменную Bitmap и затем заполн�ть ей все что угодно. Причем, объект TBitmap �вл�етс� пустым изначально, так как система не предполагает что кажда� кисть будет использовать картинку и не выдел�ет под Bitmap ни одного байта. Поэтому нужно СОЗДА�Ь объект Bitmap перед тем как загружать туда что-то. Создание объектов осуществл�етс� с помощью метода Create, который начинает свое существование с TObject. Еще одна особенность картинок дл� кистей заключаетс� в том, что дл� кисти можно использовать картинки размером 8x8 пикселов. Обидно, подумаете вы. Но на кист�х мир клином не сходитс� и если вы хотите заполн�ть что-либо большими картинками, то их можно просто изображать на Canvas-е, а не заполн�ть ими через TBrush. Ладно, отвлекс� от темы. Итак у вас есть картинка 8x8 в файле и вы хотите заполнить ей что-либо. Дл� этого ее нужно загрузить в свойство Bitmap объекта TBrush. Как уже сказано ранее Bitmap носит тип TBitmap, и объект TBitmap содержит метод LoadFromFile, позвол�ющий загрузить картинку из файла на диске. Допустим у нас есть картинка Image1.bmp и мы хотим ее загрузить. Дл� этого мы пишем:
Все, далее мы можем заполн�ть все что угодно этой картинкой. Естественно, если вы заполн�ете картинкой, то свойства Color и Style не используютс�. После того как картинка больше не нужна, нужно ее освободить, т.е. удалить. Дл� этого используетс� метод Free: Canvas.Brush.Bitmap.Free. ВАЖНО: Перед тем как загрузить другую картинку в Bitmap нужно ОЧИС�И�Ь старую методом Free. | |
  | |
TFont | |
Шрифты используютс� дл� рисовани� текста. Св�зь шрифта с TCanvas производитс� с помощью свойства Font, которое �вл�етс� объектом типа TFont. Дл� шрифта важны следующие свойства этого объекта:
Им� шрифта: Name Им� шрифта это строка в которой содержитс� его название, допустим 'Arial Cyr'. С размером шрифта вы тоже сталкивались при работе с любой программой Windows. Единственное, что можно дополнить, что здесь размер указываетс� со знаком минус, допустим -12, -14 и т.д. Цвет шрифта определ�етс� также как и цвет чего угодно другого. Идите в раздел где описываетс� TPen, чтобы узнать о том, как это делаетс�. Флаг равности символов указывает, имеют ли символы одинаковый размер или нет. Если этот флаг установлен в fpFixed, то все символы имеют одинаковый размер, если в fpVariable - разный. В данном случае подразумеваетс� ЛОГИЧЕСКИЙ размер. Физически символы не раст�гиваютс� и не сжимаютс�. Просто за размер беретс� размер самой большой буквы, допустим Ж и логический пр�моугольник вокруг каждого символа приравнивают к логическому пр�моугольнику этого символа. Просто рассто�ни� между маленькими буквами станов�тс� больше. Кодировка символов это пон�тие, идущее из глубин Windows. Дело в том, что клавиатуры бывают разные, но общее у них одно: первые 128 символов включающих английский алфавит в нижнем и ВЕРХНЕМ регистрах, цифры, скобки, точки, зап�тые и т.д. Остальные 128 символов разные дл� каждой страны, они включают алфавит этой страны и другие символы. Поэтому было придумано такое пон�тие как КОДИРОВКА и дл� каждой страны эта кодировка разна�. Поэтому нужно установить правильную кодировку дл� вашей программы, в зависимости от того, дл� какой страны вы ее пишите. Названи� всех кодировок можно прочитать в справочнике. Дл� нашей страны нужно использовать кодировку RUSSIAN_CHARSET. Нужно присвоить это значение свойству Charset. Итак, пример установки шрифта:
Canvas.Font.Name:='Arial Cyr';
| |
  | |
И�ОГ | |
Итак мы знаем, что все параметры рисовани� объекта TCanvas сосредотачиваютс� в трех объектах: Pen, Brush и Font. Pen используетс� дл� рисовани� линий и требует чтобы в нем указали стиль линии (Style), �олщину (Width) и цвет (Color). Brush используетс� дл� заполнени� фигур и использует такие параметры как цвет (Color), узор (Style) и картинку (Bitmap). При использовании картинки Style и Color не используютс�. При использовании картинки ее нужно создать, а после использовани� уничтожить. Font используетс� дл� рисовани� текста и использует такие параметры как название шрифта (Name), размер(Height), цвет(Color), флаг равности символов (Pitch) и кодировку (Charset). Итак, теперь мы знаем как заставить Canvas рисовать �АК, как нам надо. �еперь разберемс� Ч�О же можно рисовать с помощью объекта TCanvas. | |
  | |
Рисование в TCanvas | |
Прежде чем узнать о том, Ч�О рисовать, целесообразно знать ГДЕ рисовать. Хот� это не �вл�етс� фатальной вещью, однако та часть котора� выйдет за пределы контекста, будет просто отсечена. Поэтому желательно этого не допустить. В объекте TCanvas есть свойство ClipRect, в котором определены размеры пр�моугольника, за границы которого не нужно вылазить при рисовании. Это свойство имеет тип TRect, в котором имеютс� параметры:
Left - координата X левого кра� пр�моугольника �аким образом можно рисовать ориентиру�сь на эти координаты и не вылазить за их пределы. Вот например программа котора� рисует параллелограмм с диагонал�ми, вписанный в окно:
1. Можно рисовать примитивы: линии, пр�моугольники, дуги, окружности, эллипсы,многоугольники
2. Можно их заполн�ть
3. Можно рисовать текст
4. Можно вставл�ть изображени� из файлов
5. Можно брать куски одного канваса и вставл�ть в другой
6. Другие вспомогательные действи�
| |
  | |
Рисование линий и пр�моугольников | |
Насчет линий вы уже знаете. Линии рисуютс� методом LineTo, где указываетс� куда идет лини� (координаты конца). Координаты начала задаютс� методом MoveTo. Это очень важный метод. Он задает координаты так называемого КУРСОРА, или можно сказать точки отсчета, на которой будут базироватьс� фигуры. После того как вы сделали LineTo, эта точка отсчета перемещаетс� в точку конца линии и начало следующей линии уже будет в этой точке. �о же самое касаетс� и других фигур. Пр�моугольники бывают двух типов: заполненные и не заполненные. Незаполненный пр�моугольник рисуетс� с помощью метода Rectangle(X1,Y1,X2,Y2) где указываютс� координаты левого верхнего (X1,Y1) и правого нижено (X2,Y2) углов пр�моугольника. Заполненные пр�моугольники рисуютс� с помощью метода FillRect(Rect:TRECT), который требует не X1,Y1,X2,Y2, а TRect структуру в качестве координат начала и конца. Я не думаю, что это создаст дл� вас проблему. Далее идет пример использовани� этих методов:
Метод FillRect не обводит свой пр�моугольник, а просто рисует пр�моугольник, состо�щий из заполнени�. �акже существует метод FrameRect, который �вл�етс� копией FillRect, однако рисует незаполненный пр�моугольник. Использу� его, можно заменить Rectangle следующим образом:
FrameRect(Canvas.ClipRect);
�акже, можно рисовать пр�моугольники с закругленными кра�ми. Дл� этого используетс� метод RoundRect(X1,Y1,X2,Y2,X3,Y3). Здесь кроме координат начала и конца указываетс� кривизна в параметрах X3,Y3. Это, так называемые вертикальные и горизонтальные радиусы эллипса, дуга которого и будет скругл�ть каждый край пр�моугольника. Данный вид пр�моугольника обведен линией с текущими параметрами и заполнен кистью с текущими параметрами. �акже можно нарисовать пр�моугольник в стиле пр�моугольника, который по�вл�етс� на кнопке, когда она получает фокус. Дл� этого используетс� метод DrawFocusRect(Rect:TRect); Подведем итоги:
MoveTo(X,Y) - ставит координаты начала линии | |
  | |
Дуги, окружности и эллипсы | |
Дл� рисовани� дуги используетс� метод Arc(X1,Y1,X2,Y2,X3,Y3,X4,Y4). В данном случае X1,Y1,X2,Y2 это координаты пр�моугольника в который вписан эллипс. Затем из центра этого эллипса идут две логические линии в точки X3,Y3 и X4,Y4. Все, кроме той части эллипса, котора� находитс� между этими точками эллипса отсекаетс�. �аким образом получаетс� дуга. �акже существует метод Chord(X1,Y1,X2,Y2,X3,Y3,X4,Y4), который рисует дугу и соедин�ет ее кра� линией. Это уже получаетс� замкнута� фигура, котора� обводитс� линией и заполн�етс� текущей кистью. Эллипс рисуетс� с помощью метода Ellipse(X1,Y1,X2,Y2), где в качестве параметров указываютс� координаты логического пр�моугольника, в который вписываетс� эллипс. Эллипс �вл�етс� фигурой замкнутой и поэтому обводитс� текущей линией и заполн�етс� текущей кистью. �акже можно нарисовать сектор эллипса с помощью функции Pie(X1,Y1,X2,Y2,X3,Y3,X4,Y4). �ехнологи� рисовани� сектора такова. Сначала рисуетс� эллипс, вписанный в пр�моугольник X1,Y1,X2,Y2 и затем из его центра рисуютс� линии концы которых идут в точки X3,Y3 и X4,Y4. Все, кроме того что находитс� между этими лин�ми убираетс� и полученна� фигура �вл�етс� сектором. Сектор, это тоже фигура замкнута� и поэтому обводитс� и заполн�етс�. Подведем итоги:
Arc(X1,X2,Y1,Y2,X3,Y3,X4,Y4) - рисует дугу - часть эллипса между точками X3,Y3,X4,Y4 | |
  | |
Многоугольники и ломанные | |
Ломанную линию можно нарисовать с помощью метода PolyLine. В качестве параметра, эта функци� принимает массив точек. Кажда� точка это переменна� типа TPoint, у которой есть два параметра: X и Y. В массиве может быть любое количество точек. Данный метод просто соедин�ет их, образу� ломанную. Вот пример:
Этот пример рисует ломанную линию из четырех сегментов. Можно замкнуть ее, указав в качестве последней точки начало ломанной. �огда получитс� многоугольник, однако заполнен он не будет, так как все равно считаетс� ломанной. А дл� того чтобы нарисовать заполненный многоугольник, используетс� метод Polygon, который также требует в качестве параметра массив точек и соедин�ет начало и конец ломанной за вас, образу� многоугольник. �акже он обводит его линией и заполн�ет текущей кистью. Следующие два метода � не знал к чему отнести, то ли к кривым, то ли к многоугольникам. Однако отнес к многоугольникам, так как методы очень похожи на многоугольники по своей структуре. Эти методы предназначены дл� рисовани� кривых безье. Метод PolyBezier рисует ломанную линию преобразованную в дугу. Первый сегмент состоит из четырех точек: начала, конца и двух контрольных точек между ними, последующие сегменты состо�т из трех точек, так как используют конец предыдущего в качестве своего начала. Однако эта функци� все это просит в виде одного массива точек, как и предыдущие. Просто оно разбивает их на сегменты дл� того чтобы точнее и плавнее преобразовывать линии в дуги. Данна� функци� не заполн�ет получившуюс� фигуру. �акже существует метод PolyBezierTo, который делает то же самое, что и PolyBezier, но устанавливает КУРСОР в конец последнего сегмента (просто выполн�ет MoveTo дл� этой точки). Подведем итоги Дл� рисовани� ломанных пр�мых линий и многоугольников существуют методы Polyline(Points: array of TPoint) и Polygon(Points: array of TPoint). Оба требуют массива точек, последний замыкает начало и конец ломаной образу� многоугольник и заполн�ет его. Дл� рисовани� кривых ломанных линий используютс� методы PolyBezier(Points: array of TPoint) и PolyBezierTo(Points: array of TPoint), которые также требуют массив точек. Дл� точного преобразовани�, каждый сегмент состоит из четырех точек: начала, конца и двух контрольных точек между ними. По этим четырем точкам плавно проводитс� дуга. PolyBezierTo устанавливает курсор в позицию последней точки. | |
  | |
Работа с текстом | |
�екст непосредственно выводитс� с помощью функций TextOut(X,Y,S), где X,Y это координаты текста и S, это строка текста и TextRect(Rect:TRect,X,Y,S), где кроме всех этих параметров указываетс� Rect - логический пр�моугольник, в который этот текст должен быть вписан. Весь текст, который выходит за пределы этого пр�моугольника отсекаетс�. �акже можно определ�ть ширину и высоту строки текста, прежде чем выводить его. Дл� этого используютс� функции TextWidth(S) и TextHeight(S). Перва� дл� ширины текста, а втора� дл� высоты. В обоих указываетс� строка. Эти функции можно присвоить переменным числового типа:
�акже существует функци� TextExtent(S), котора� возвращает значение типа TSize. TSize содержит параметры cx и cy, которые содержат длину и ширину строки. Это то же самое, что и использовать две предыдущие функции. Однако удобнее, так как меньше переменных и строк кода. Подведем итоги: �екст можно вывести в указанную точку с помощью метода TextOut(X,Y,S), а также в указанную точку ограничивающего пр�моугольника с помощью метода TextRect(Rect:TRect,X,Y,S);. Предварительно можно определить ширину (TextWidth(S)) и высоту(TextHeight(S)) текста. Либо все сразу - TextExtent(S). | |
  | |
Заполнение | |
Мы говорили раньше о том, что бывают заполненные фигуры или не заполненные. Почему бы не заполн�ть все что угодно? Дл� этого используетс� метод FloodFill(X,Y,Color,FillStyle). �еперь подробнее о том, как работает этот метод. Он начинает работать, заполн�� все точки вокруг X,Y текущей кистью. Если FillStyle=fsSurface, то он заполн�ет только точки цвета Color и не ведет заполнение при встрече точки другого цвета, т.е пытаетс� ее обойти. Если этого не удаетс�, то метод прекращает работу. Если FillStyle=fsBorder, то метод заполн�ет все точки которые НЕ имеют цвет Color, а в остальном действует также как и в первом случае. Color в данном случае указываетс� как и любой другой цвет (см. описание объекта TPen в данном обзоре). | |
  | |
Работа с картинками | |
Как говорилось ранее, можно вставл�ть картинки из файлов на рабочую область TCanvas-а, а также брать куски одного Canvas-а, переносить их в другой. Здесь все эти хитрые манипул�ции будут рассмотрены. Дл� того чтобы вставить картинку используетс� функци� Draw(X,Y,Bitmap). X,Y это координаты точки, в которую вставить картинку, а Bitmap это объект типа TBitmap, представл�ющий из себ� картинку. Дл� того чтобы поместить картинку в Canvas, нужно сначала выделить пам�ть под этот объект и загрузить в него картинку откуда-нибудь, с диска например:
Данный пример рисует картинку из файла image1.bmp в позиции 20,20 указанного Canvas-а. Метод StretchDraw(Rect:TRect,Bitmap:TBitmap) рисует картинку вписыва� ее в указанный логический пр�моугольник Rect, при необходимости раст�гива� или сплющива� ее (измен�� масштаб, если быть культурнее). �акже, можно очень хитро рисовать картинки. Самым хитрым методом дл� рисовани� картинки на Canvas-е � по праву считаю метод BrushCopy(Dest:TRect; Bitmap:TBitmap; Source:TRect; Color:TColor); Данный метод рисует кусок изображени� Bitmap ограниченный пр�моугольником Source в пр�моугольнике Dest, при необходимости раст�гива� или сплющива� его. �акже, этот метод не изображает все точки с цветом Color на Canvas-е, осуществл�� таким образом эффект прозрачности. Вот такие вот штуки можно Canvas-ом творить! �акже можно копировать кусок одного Canvas-а в другой, т.е. часть изображени� из контекста одного элемента управлени�, (или формы, или окна или чего угодно другого) в указанное место контекста другого элемента управлени�. Это делаетс� методом CopyRect(Dest:TRect; Canvas:TCanvas; Source: TRect);. Данный метод копирует участок изображени� текущего Canvas-а, вписанный в пр�моугольник Source в пр�моугольник Dest указанного Canvas-a. При этом участок Canvas-а назначени� раст�гиваетс� или сплющиваетс� нужным образом. | |
  | |
Другие операции | |
Есть еще несколько методов, которые � ни к чему не смог отнести. Во первых это набор методов защиты от рисовани� других потоков данной программы в указанном Canvas-е. Это нужно делать в том случае, если ваша программа многопоточна и есть возможность, что другой поток может нарисовать что-то в то врем�, как Canvas текущего потока что-либо рисует. В этом случае результат может быть нежелательным. Чтобы предотвратить подобный эффект нужно "замкнуть Canvas" методом Lock, затем нарисовать все что нужно и "разомкнуть" его методом Unlock. �акже, если ваша программа настолько больша�, что вы уже сами не знаете, что натворили две недели назад, существует метод TryLock, который сначала проверит, замкнут ли данный Canvas или нет, и если нет, то замкнет. �акже существует метод Refresh, который удал�ет текущие настройки Pen, Brush и Font, возвраща� их в состо�ние по умолчанию. Естественно, как и в любом объекте, в объекте TCanvas существуют такие методы как Create и Destroy. Первый создает Canvas и выдел�ет под него пам�ть, второй уничтожает и освобождает выделенную пам�ть. Нежелательно уничтожать и создавать Canvas-ы, встроенные в элементы управлени�. За это отвечает Delphi. Этими методами вам придетс� пользоватьс� при создании своих собственных, логических Canvas-ов. | |
  | |
Заключение | |
Вот и все, что вы можете делать с TCanvas. Все методы работают основыва�сь на установках Pen, Brush и Font. Вот полный список:
ЛИНИИ И ПРЯМОУГОЛЬНИКИ
ДУГИ
МНОГОУГОЛЬНИКИ
�ЕКС�
ЗАПОЛНЕНИЕ
КАР�ИНКИ
ЗАЩИ�А
ДРУГИЕ ОПЕРАЦИИ
ВСЕГО: 31 метод. | |
  | |
Внутренний механизм TCanvas | |
�о что � расскажу сейчас не потребуетс� дл� того чтобы нарисовать какую-нибудь картинку в форме. Это потребуетс� дл� того чтобы знать, как TCanvas ув�зан с графическим механизмом Windows. Итак, каждый элемент управлени� в котором можно рисовать содержит Canvas. Объект TCanvas имеет свойство Handle типа HDC, это и есть контекст окна элемента управлени�. Каждый графичекий метод перекодируетс� в аналогичный графический метод (или набор) Win32 API, в котором �вно указываетс� эта ссылка на контекст. Допустим Canvas.LineTo(X,Y) перекодируетс� в аналогичную функцию Win32.API LineTo(Canvas.Handle,X,Y), где �вно указываетс� ссылка на контекст. �акже точно при установке пера, кисти и шрифта, устанавливаютс� соответствующие объекты Win32 API : HPEN, HBRUSH и HFONT помещаютс� в Handle. Вот как это в Win32 API делаетс�:
Дело в том, что дл� св�зи с Win32 API в объектах TPen, TFont и TBrush тоже есть свойство Handle, указывающее на данный объект уровн� Win32 API. В TPen - Handle имеет тип HPEN, в TBrush - Handle имеет тип HBRUSH и в TFont - Handle имеет тип HFONT. �аким образом все направл�етс� на Handle объекта Canvas. �ак как Handle �вл�етс� контекстом, то естественно Windows правильно рисует в нем. Каким же образом это Handle инициализируетс�? Очень просто! Дело в том, что у всех ОКОННЫХ элементов управлени� тоже есть сво� Handle, котора� объ�влена на уровне TWinControl - предка всех оконных элементов управлени�. В данном случае Handle имеет тип HWND, а HWND это оконна� ссылка. Чтобы получить контекст, нужно указать окно, дл� которого его нужно получить. Окно в Win32 API указываетс� в виде ссылки. Контекст можно получить функцией Win32 API GetDC. Эту операцию вам делать не приходитс�, она происходит автоматически. Вот, например, как Delphi получает контекст дл� формы Form1. Form1.Canvas.Handle:=GetDC(Form1.Handle); Функци� GetDC берет ссылку на окно формы в качестве параметра. Итак, алгоритм таков. Сначала TCanvas получает ссылку на контекст своего элемента управлени� использу� его оконную ссылку. Затем он выполн�ет графические операции на эту контекстную ссылку Handle, а при изменении параметров рисовани�, он пользуетс� услугами объектов TPen, TBrush и TFont, которые занос�т все изменени� в свои свойства более низкого уровн� HPEN, HBRUSH и HFONT. Эти свойства нужным образом передаютс� в Handle TCanvas-а. Вот таким образом изнутри выгл�дит процесс рисовани� в окнах. | |
  | |
Общее заключение | |
Я думаю, что довольно детально разобрал TCanvas. Причем ИМЕННО TCanvas. Здесь также упоминались довольно важные вещи, такие как Win32 API или объект TBitmap. Второе здесь очень кратко затронуто, но � бы порекомендовал почитать об этом подробнее. По этому поводу у мен� есть стать�. TBitmap это фундаментальный объект рисовани� в Windows. �акже последний раздел может вселить определенные непон�тности. Дело в том, что многие элементы управлени� вообще не имеют свойства TCanvas, хот� и �вл�ютс� ОКНАМИ. Поэтому � изложил внутренний механизм работы TCanvas дл� того, чтобы вы пон�ли, что не на TCanvas-е мир клином сошелс�, что можно рисовать в любом окне. И в качестве продолжени� этой темы � порекомендовал бы почитать статью "Как рисовать где угодно", в которой изложен метод хитрого обмана Delphi, позвол�ющего рисовать в любых элементах управлени� и в любых их местах. А теперь, пожалуй все. Прочтите это еще пару раз (не так уж и много!!!) и об�зательно пробуйте. Удачного Вам рисовани�. С Уважением, А.Германов. |