Создание региона
Запускаем среду, заводим новый проект,
тщательно сохраняем куда попало. В
обработчике OnCreate пишем
первое, что,
по идее,
приходит в
голову:
procedure
TForm1.FormCreate(Sender: TObject);
var
r:
hRGN;
begin
r
:= CreateEllipticRgn (0, 0, Width, Height);
try
SetWindowRgn
(Handle, r, TRUE);
finally
DeleteObject
(r);
end;
end;
Результатом запуска окажется симпатичный
эллипс на экране. А теперь попробуйте
дописать такой простенький обработчик
на OnKeyPress:
procedure
TForm1.FormKeyPress(Sender: TObject; var Key: Char);
var
bmp:
TBitmap;
begin
if Key
= 'p' then begin
bmp :=
GetFormImage;
try
bmp.SaveToFile
('c:\temp.bmp');
finally
bmp.Free;
end;
end;
end;
Аналогичным образом создаются и другие типы регионов, единственное внимание стоит, пожалуй, уделить полигональным. Начнём с самого простого. В делкарации функции есть интересный параметр: FillMode. Согласно SDK он может принимать два значения - ALTERNATE и WINDING. Со вторым всё просто - вычисляются границы, и всё, что между - заливается текущей кистью. А вот первый при заливке анализирует, по какую сторону ребра (чётную или нечётную) он находится. Что это означает, мы увидим на следующем примере.
procedure TForm1.FormCreate(Sender:
TObject);
var
ap:
array [1..5] of TPoint;
r:
hRGN;
begin
ap
[1] := Point (Width div 2, 0);
ap
[2] := Point (Width div 3 * 2, Height);
ap
[3] := Point (0, Height div 3);
ap
[4] := Point (Width, Height div 3);
ap
[5] := Point (Width div 3, Height);
r
:= CreatePolygonRgn (ap, 5, WINDING);
try
SetWindowRgn
(Handle, r, TRUE);
finally
DeleteObject
(r);
end;
end;
Теперь разберёмся, как работает функция CreatePolyPolygonRgn. Её предназначение в том, чтобы рисовать сразу несколько регионов, которые могу даже не пересекаться. А могу - и пересекаться, именно для этого и нужен параметр FillMode. Поглядим, как это выглядит, и что оно делает:
procedure TForm1.FormCreate(Sender:
TObject);
var
ap:
array [1..7] of TPoint;
av:
array [1..2] of integer;
r:
hRGN;
begin
ap
[1] := Point (0, 0);
ap
[2] := Point (Width, 0);
ap
[3] := Point (Width, Height div 2);
ap
[4] := Point (0, Height div 2);
ap
[5] := Point (Width div 2, Height div 2);
ap
[6] := Point (0, Height);
ap
[7] := Point (Width, Height);
av
[1] := 4;
av
[2] := 3;
r
:= CreatePolyPolygonRgn (ap, av, 2, WINDING);
try
SetWindowRgn
(Handle, r, TRUE);
finally
DeleteObject
(r);
end;
end;
Комбинирование регионов
Результат комбинирования определяется четвёртым параметром функции CombineRgn. Давайте посмтрим, какие значения он может принимать.
RGN_ADD
Пересечение двух регионов p2 и p3
RGN_COPY
Создаёт копию региона p2
RGN_DIFF
Вернёт часть p2, не являющуюся частью p3
RGN_OR
Объединение двух регионов p2 и p3
RGN_XOR
Объединяет регионы p2 и p3, исключая пересекающиеся области
Возвращаемые значения могут быть NULLREGION (пустой регион), SIMPLEREGION (один прямоугольник), COMPLEXREGION (всё остальное) и ERROR (не создано). Посмотрим, как это выглядит на практике (дописываем предыдущий пример).
procedure TForm1.FormCreate(Sender:
TObject);
var
ap:
array [1..7] of TPoint;
av:
array [1..2] of integer;
r,
r2, r3, r4: hRGN;
begin
ap
[1] := Point (0, 0);
ap
[2] := Point (Width, 0);
ap
[3] := Point (Width, Height div 2);
ap
[4] := Point (0, Height div 2);
ap
[5] := Point (Width div 2, Height div 2);
ap
[6] := Point (0, Height);
ap
[7] := Point (Width, Height);
av
[1] := 4;
av
[2] := 3;
r
:= CreatePolyPolygonRgn (ap, av, 2, WINDING);
try
r2
:= CreateRoundRectRgn
(Width
div 4 - 20, Height div 6 - 20,
Width
div 4 + 20, Height div 6 + 20, 16, 16);
r3
:= CreateRoundRectRgn
(Width
div 4 * 3 - 20, Height div 6 - 20,
Width
div 4 * 3 + 20, Height div 6 + 20, 16, 16);
r4
:= CreateEllipticRgn
(Width div 10, Height div 9 * 3,
Width
div 10 * 9, Height div 9 * 4);
try
CombineRgn
(r, r, r2, RGN_XOR);
CombineRgn
(r, r, r3, RGN_XOR);
CombineRgn
(r, r, r4, RGN_XOR);
finally
DeleteObject
(r2);
DeleteObject
(r3);
DeleteObject
(r4);
end;
SetWindowRgn
(Handle, r, TRUE);
finally
DeleteObject
(r);
end;
end;
Нерасмотренной из первой группы функций осталась только ExtCreateRgn. Я сейчас не буду на ней заостряться, скажу только, что на пару с функцией GetRegionData, она может пригодиться, например, для сохранения и загрузки регионов в файл / из файла.
