16.4.4.2. Области
К сожалению, в класс TCanvas не включена еще одна изобразительная возможность Windows - области (Regions). Области - такие же графические объекты, как перо, кисть, шрифт. Они образуются с помощью комбинации простейших геометрических фигур - прямоугольников, многоугольников, эллипсов. Замечательной особенностью областей является возможность создания с их помощью непрямоугольных кнопок, цветовых областей, окон. А вот как оно было создано:
uses
Forms,
Unit1 in 'Unitl.pas' {Formi}, Windows; // Этот модуль экспортирует функции API
{$R *.RES} var
Rgn: Cardinal;
begin
// Сначала создаем обычное окно:
Application.CreateForm(Tform1, Form1);
with Formi.Canvas, Formi do
begin
// Теперь создаем в нем эллиптическую область
Rgn := CreateEllipticRgn(0, 0, Width, Height);
// и показываем ее вместо окна
SetWindowRgn(Handle, Rgn, True);
end;
Application.Run;
end.
Ниже перечислены основные функции для работы с областями.
Работа с областями
function CombineRgn(DestRgn, Rgnl, Rgn2: Cardinal; Com-bineMode: Ineger): Integer; |
Объединяет две области в одну: DestRgn - дескриптор результирующей области; Rgnl, Rgn2 -дескрипторы объединяемых областей; CombineMode - параметр, указывающий способ объединения; этот параметр, а также возвращаемое значение описаны ниже |
function CreateEllipticRgn(XI, Yl, X2, Y2: Integer) : Cardinal; |
Создает эллиптическую область |
function CreatePoly-gonRgn(var Points; Count, PolyFillMode: Integer): Cardinal; |
Создает область в виде многоугольника: Points - массив координат всех вершин многоугольника; Count - количество вершин; PolyFillMode -режим заполнения многоугольника (см. ниже) |
function CreateRectRgn(XI, Yl, X2, Y2: Integer): Cardi nal; |
Создает прямоугольную область
|
function CreateRoundRectRgn(Xl, Yl, X2, Y2, X3, Y3: Integer): Cardinal; |
Создает область со скругленными углами; параметры обращения иллюстрирует |
function EqualRgn(Rgnl,Rgn2: Cardibal): Bool; |
Проверяет эквивалентность двух областей |
function FillRgn(DC, Rgn,Brush: Cardinal): Bool; |
Закрашивает область кистью: DC - дескриптор канвы окна; Rgn - дескриптор области; Brush - дескриптор кисти |
function FrameRgn(DC, Rgn,Brush: Cardinal; Width,Height: Integer): Bool; |
Обводит (но не заполняет) область кистью высотой Height и шириной Width пикселей |
function InvertRgn(DC, Rgn:Cardinal): Bool; |
Инвертирует все пиксели внутри области |
function OffsetRgn(DC, Rgn:Cardinal; dX, dY: Integer):Integer; |
Смещает область на dX по горизонтали и на dY по вертикали |
function PaintRgn(DC, Rgn:Cardinal): Bool; |
Закрашивает область текущей кистью
|
function PtInRegion(Rgn:Cardinal; X, Y: Integer):Bool; |
Проверяет принадлежность точки (X,Y) области Rgn |
function RectInRegion(Rgn:Cardinal; Rect: TRect):Bool; |
Проверяет принадлежность прямоугольника Rect области Rgn
|
function SetWindowRgn(DC,Rgn: Cardina; Redraw: Bool): Integer;
|
Показывает принадлежащую окну с канвой DC область Rgn вместо окна; Redraw- разрешает/запрещает перерисовку области; все не вошедшие в область части окна не показываются (см. ниже) |
Параметр combineMode в функции combineRgn может значения:
rgn_and - включает в результат общие части областей; rgn_copy -копирует область Rgnl В DestRgn; RGN_DIFF - исключает изRgnl часть, принадлежащую Rgn2; rgn_or - объединяет области; rgn_xor -включает в результат только те части областей, которые не принадлежат им одновременно. Область DestRgn уже должна существовать и иметь размеры, достаточные для размещения объединенной области. При обращении к функции createPoiygonRgn параметр Poly FillMode может иметь значения: Alternate И Winding. В первом случае заполнение многоугольника идет последовательно между двумя близлежащими его сторонами: сначала между 1-й и 2-й, затем между 2-й и 3-й и т. д. В режиме winding заполняется все внутреннее пространство области.
Во всех случаях Windows автоматически проводит линию между последней и первой точкой многоугольника, делая его замкнутым.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls;
tуре
Tform1 = class (TForm)
PaintBoxl: TPaintBox;
PaintBox2: TPaintBox;
Button1: TButton;
procedure ButtonlClick(Sender: TObject);
private
{ Private declarations } public
{ Public declarations } end;
var
Form1: Tform1;
implernentation
$R *.DFM)
procedure TFormI.ButtonlClick(Sender: TObject);
var
Rgnl, Rgn2: Cardinal;
const
Points: array [1..5, 1..2] of Integer =
C(91, 0), (160, 183), (0, 70), (183, 70), (23, 183));
begin
Rgn1 := CreatePolygonRgn(Points, 5, Alternate);
Rgn2 := CreatePolygonRgn(Points, 5, Winding);
with PaintBoxl.Canvas do begin
Brush.Color := clBlack;
FillRgn(Handle, Rgnl, Brush.Handle);
end;
with PaintBox2.Canvas do begin
Brush.Color := clBlack;
FillRgn(Handle, Rgn2, Brush.Handle) ;
end;
end;
end.
Обратите внимание: прорисовка и объединение областей доступны, только если области видны в окне (для создания предыдущего рисунка нельзя, например, использовать обработчик формы OnActivate).
Функция SetWindowRgn, как уже отмечалось, поручает прорисовку окна самой Windows, при этом фактически прорисовывается не область, а лишь та часть окна, которая ограничена ею. Любые заливки области, ее очерчивание и объединение с другими областями игнорируются.