Delphi - Статьи - Работа с хослстом в Delphi

При создании программ, возникает необходимость украшения её элементов (применение градиентной заливки, прорисовка логотипов на форме, создание различных анимированных эффектов), постоянно возникает потребность переработки стандартных компонентов Delphi (изменение внешнего вида, перемещение заголовка в нужное место, создание многострочных заголовков). Именно для этого и используется Canvas(холст).

Что можно делать на холсте?
1. Рисовать различные геометрические фигуры.
2. Помещать на него изображения.

Что оно такое?
Это свойство.Оно принадлежит изначально многим компонентам, наследникам от TGraphicsControl. Свойства Canvas имеют тип TCanvas и почти эквивалентны контексту устройства Windows. На самом деле проще воспринимать холст, как некий слой элемента (формы, этикетки и т.д.).

Начало.
Общий случай применения холста в программе:


procedure TForm1.TempCanvas(MyCanvas:TCanvas);
begin
with MyCanvas do begin //Работаем с холстом
{Подготовка к работе}
Pen.Style:=psSolid;//Стиль пера
Pen.Color:=clRed; //Цвет пера
Brush.Style:=bsSolid;//Стиль кисти
Brush.Color:=clGreen;//Цвет кисти
Font.Color:=clWhite; //Цвет шрифта
{Работа}
MoveTo(20,20); //Поставить перо в точку 20,20
LineTo(120,20); //Провести прямую линию до точки 120,20 и переместить в неё перо.
Rectangle(20,40,120,80); //Чертить прямоугольник
RoundRect(20,100,120,140,10,20);//Чертить прямоугольник со скруглёнными углами
Ellipse(20,160,120,200); //Чертить эллипс
TextOut(20,220,′Рисуем на холсте′);//Вывести текст
end;
end;

и вызов данной процедуры может быть таким:


procedure TForm1.FormPaint(Sender: TObject);
begin
TempCanvas(Form1.Canvas);//В качестве параметра передаём холст формы
end;

Подготовительный этап: Установка параметров холста для рисования
Работа: Непосредственное отображение элементов с установленными на подготовительном этапе параметрами.
Это не означает, что только с такими параметрами мы и можем рисовать на холсте. Мы можем менять параметры в любом месте программы, где они видимы, и соответственно дальнейший процесс рисования у нас будет идти уже с новыми параметрами.
Пример:


procedure TForm1.TempCanvas(MyCanvas:TCanvas);
var i:Integer;
begin
randomize;//Инициализируем ГСЧ
with MyCanvas do
for i:=0 to Width do begin //от 0 до Ширины холста
Pen.Color:=Random($FFFFFF);//Изменяем цвет пера на случайный
MoveTo(i,0);
LineTo(i,Height);
end;
end;

Или так:


procedure TForm1.TempCanvas(MyCanvas:TCanvas);
var i,h:Integer;
begin
randomize;
if Width>Height then h:=Width else h:=Height;
with MyCanvas do
for i:=0 to h div 2 do begin
Pen.Color:=Random($FFFFFF);
MoveTo(i*2,0);
LineTo(i*2,Height);
MoveTo(0,i*2);
LineTo(Width,i*2);
end;
end;

Интересный эффект?
Используя изменение свойств холста можно добиться и большего...
Например эффект "Северное сияние"


procedure TForm1.TempCanvas(MyCanvas:TCanvas);
var i:Integer;
begin
randomize;
with MyCanvas do
for i:=0 to Width do begin
Pen.Color:=Random($FFFFFF);
MoveTo(i,0);
LineTo(i,Height);
end;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
TempCanvas(Form1.Canvas);
end;

где интервал таймера 150.

Это далеко не все прелести холста.
Рисуем кнопку.


procedure TForm1.DrawButton(MyCanvas:TCanvas; Caption:String; X,Y,W,H,Border:Integer; Color:TColor; Flat:Boolean);
var
i,j:Integer;
begin
randomize;
with MyCanvas do begin
Brush.Color:=Color;
Pen.Color:=Color;
Rectangle(X,Y,X+W,Y+H);//Рисуем прямоугольник кнопки
if not Flat then //Если кнопка не плоская
for i:=0 to Border do begin //Рисуем фаску (Бордюр)
Pen.Color:=clWhite; //Левая и верхняя часть белая
MoveTo(X+i,Y+H-i);
LineTo(X+i,Y+i);
LineTo(X+W-i,Y+i);
Pen.Color:=clGray; //Правая и нижняя часть серая
LineTo(X+W-i,Y+H-i);
LineTo(X+i,Y+H-i);
end;
i:=TextHeight(Caption);//Высота текста
j:=TextWidth(Caption); //Ширина текста
TextOut(X+(W-j) div 2,Y+(H-i)div 2,Caption); //Нарисовать текст заголовка
end;
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
DrawButton(Form1.Canvas,′Button1′,20,20,50,20,2,clBtnFace,false);
DrawButton(Form1.Canvas,′Button2′,20,50,50,20,2,clBtnFace,true);
end;


Это конечно же не настоящая кнопка, но примерно так она и рисуется...
Вы могли заметить, что наша кнопка пребрела элементы объёма. Как это делать и всё, что касается работы с Цветом Смотрите в статье Color и с чем его едят;
Можно пойти дальше и обработать нашу "кнопку" событиями... Но это другая тема...
Продолжим...

В связи с тем, что свойство Canvas встречается во многих компонентах Delphi, то мы имеем возможность менять их внешний вид.
Например: нам нужно, чтобы заголовок на панели мог позиционироваться по девяти позициям.
Мы создаём наш, новый класс TsfPanel=class(TCustomPanel);


unit Unit2;

interface
uses ExtCtrls,Classes;
type
TVAlignment=(inTop,inCenter,inBottom); //Наш тип
TsfPanel=class(TCustomPanel) //Наш класс
private
fVAlignment:TVAlignment;
procedure SetVAlignment(Value:TVAlignment);
protected

procedure Paint;override;
public
property VAlignment:TVAlignment read fVAlignment write SetVAlignment;
property Alignment;
property Color;
constructor Create(AOwner:TComponent);override;
property BorderWidth;
property BevelWidth;
property Caption;
property Font;
end;

implementation

uses Graphics, Controls,Windows,Types;

constructor TsfPanel.Create(AOwner:TComponent);
begin
inherited Create(AOwner);
BorderWidth:=2;
Color:=clBtnFace;
Font.Color:=clBlack;
ControlStyle:=ControlStyle-[csSetCaption,csOpaque];
end;

procedure TsfPanel.SetVAlignment(Value:TVAlignment);
begin
if Value <> fVAlignment then fVAlignment:=Value;
Paint;
end;


//Самое интересное тут

procedure TsfPanel.Paint;
var
CaptionRect:TRect;
H,C:Integer;
begin
case ord(Alignment) of //Инициализируем применительно к нам
//свойство горизонтального позиционирования
0:C:=0;
1:C:=2;
2:C:=1;
else c:=0;
end;

With Canvas, CaptionRect do begin //Рисуем
Rectangle(BorderWidth,BorderWidth,Width-BorderWidth,Height-BorderWidth); //Прямоугольник панели
For H:=0 to BorderWidth do begin //Рамку панели
Pen.Color:=clWhite;
MoveTo(Width-H,H);
LineTo(H,H);
LineTo(H,Height-H);
Pen.Color:=clGray;
LineTo(Width-H,Height-H);
LineTo(Width-H,H);
end;
Font:=Self.Font; //Устанавливаем параметры шрифта
CaptionRect:=Rect(2,2,Width-2,Height-2); //Инициализируем размер прямоугольника для заголовка
Brush.Style:=bsClear ;
H:= TextHeight(Caption); //Узнаём текущую высоту заголовка
case VAlignment of //Устанавливаем верх текста
inCenter: begin
Top:=((Bottom+Top)-H)shr 1;
Bottom:=Top+H;
end;
inBottom: Top:=Bottom-H-1;
end;
DrawText(Handle,PChar(Caption),-1,CaptionRect,C); //Рисуем текст
end;
end;
end.

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

Создадим новый проект, подключим к нему наш модуль....
Напишем в нашем проекте код на события формы OnCreate и OnDestroy

...
var
Form1: TForm1;
MyPanel:TsfPanel;
implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
MyPanel:=TsfPanel.Create(self);
MyPanel.Parent:=self;
MyPanel.VAlignment:=inTop;
MyPanel.Alignment:=taLeftJustify;
MyPanel.Top:=100;
MyPanel.Left:=150;
MyPanel.Height:=120;
MyPanel.Width:=120;
MyPanel.Caption:=′Проба′;
MyPanel.Visible:=True;
MyPanel.Font.Color:=clBlack;
Invalidate;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
MyPanel.Free;
end;

Запустим его... и вот она наша панелька...
Меняя значения MyPanel.VAlignment и MyPanel.Alignment, мы бросаем заголовок в одно из 9-ти положений...
Заметьте, что у Настоящей панели нет свойства Canvas, у нашей тоже нет... Но при желании, можно и это сделать... Главное родителя нашей панели правильно выбрать...

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

По материалам: www.excode.ru
Copyright © 2006-09.