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, при этом фактически прорисовывается не область, а лишь та часть окна, которая ограничена ею. Любые заливки области, ее очерчивание и объединение с другими областями игнорируются.