points[0].X:= 0;
points[0].Y:= height 1;
points[1].X:= width div 2;
points[1].Y:= 0;
points[2].X:= width 1;
points[2].Y:= height 1;
end;
В листинге 1.14 приведено описание процедуры создания шестиугольника.
Листинг 1.14. Создание шестиугольникаprocedure Make6Angle(width, height: Integer; var points: array of TPoint);
begin
points[0].X:= 0;
points[0].Y:= height div 2;
points[1].X:= width div 3;
points[1].Y:= 0;
points[2].X:= 2 * (width div 3);
points[2].Y:= 0;
points[3].X:= width 1;
points[3].Y:= height div 2;
points[4].X:= 2 * (width div 3);
points[4].Y:= height 1;
points[5].X:= width div 3;
points[5].Y:= height 1;
end;
Листинг 1.15 содержит описание процедуры создания пятиугольника (неправильного).
Листинг 1.15. Создание пятиугольникаprocedure Make5Angle(width, height: Integer; var points: array of TPoint);
var a: Integer; //Сторона пятиугольника
begin
a:= width div 2;
points[0].X:= a;
points[0].Y:= 0;
points[1].X:= width 1;
points[1].Y:= a div 2;
points[2].X:= 3 * (a div 2);
points[2].Y:= height 1;
points[3].X:= a div 2;
points[3].Y:= height 1;
points[4].X:= 0;
points[4].Y:= a div 2;
end;
Пятиугольная звезда, используемая как область отсечения формы, создается с помощью описанной в листинге 1.15 процедуры Make5Angle. После ее создания изменяется порядок следования вершин пятиугольника, чтобы их обход при построении региона выполнялся в той же последовательности, как рисуется звезда карандашом на бумаге (например, 1-3-5-2-4) (листинг 1.16).
Листинг 1.16. Создание пятиугольной звездыprocedure MakeStar(width, height: Integer; var points: array of TPoint);
begin
Make5Angle(width, height, points);
//При построении звезды точки пятиугольника обходятся не по порядку,
//а через одну
Swap(points[1], points[2]);
Swap(points[2], points[4]);
Swap(points[3], points[4]);
end;
Процедура MakeStart (листинг 1.16) использует дополнительную процедуру Swap, меняющую местами значения двух передаваемых в нее аргументов. Процедура Swap реализуется чрезвычайно просто и потому в тексте книги не приводится.
Комбинированные регионы
Вы уже научились создавать и использовать простые регионы. Однако многим может показаться недостаточным тех форм окон, которые можно получить с использованием в качестве области отсечения лишь одного несложного региона. Пришло время заняться созданием окон более сложной формы, применяя рассмотренные ранее операции над регионами.
«Дырявая» формаЭтот простейший пример сомнительной полезности предназначен для первого знакомства с операциями над регионами. Здесь применяется только одна из возможных операций операция XOR для формирования «дырок» в форме (рис. 1.8).
Рис. 1.8. «Дырки» в форме
На рис. 1.8 явно видно, как в «дырках» формы просвечивает одно из окон среды разработки Delphi. При этом, когда указатель находится над «дыркой», сообщения от мыши получают те окна, части которых видны в «дырке».
Программный код, приводящий к созданию формы столь необычного вида, приведен в листинге 1.17.
Листинг 1.17. Создание «дырок» в формеprocedure TfrmHole.FormCreate(Sender: TObject);
var
rgn1, rgn2: HRGN; //"Регионы-дырки" в форме
formRgn: HRGN;
begin
//Создание региона для формы
formRgn:= CreateRectRgn(0, 0, Width 1, Height 1);
//Создание регионов для "дырок"
rgn1:= CreateEllipticRgn(10, 10, 100, 50);
rgn2:= CreateRoundRectRgn(10, 60, 200, 90, 10, 10);
//Создание "дырок" в регионе формы
CombineRgn(formRgn, formRgn, rgn1, RGN_XOR);
CombineRgn(formRgn, formRgn, rgn2, RGN_XOR);
SetWindowRgn(Handle, formRgn, True);
//Регионы для "дырок" больше не нужны
DeleteObject(rgn1);
DeleteObject(rgn2);
end;
Сложная комбинация регионов
Теперь пришла очередь рассмотреть более сложный, но и гораздо более интересный пример. Последовательное применение нескольких операций над регионами приводит к созданию формы, показанной на рис. 1.9 (белое пространство «вырезанные» части формы).
Рис. 1.9. Сложная комбинация регионов
Описание процедуры, выполняющей операции над регионами, приведено в листинге 1.18.
Листинг 1.18. Сложная комбинация регионовprocedure TfrmManyRgn.FormCreate(Sender: TObject);
var
r1, r2, r3, r4, r5, r6, r7: HRGN;
formRgn: HRGN;
butRgn: HRGN;
begin
//Создание регионов
r1:= CreateRoundRectRgn(100, 0, 700, 400, 40, 40);
r2:= CreateRectRgn(280, 0, 300, 399);
r3:= CreateRectRgn(500, 0, 520, 399);
r4:= CreateEllipticRgn(140, 40, 240, 140);
r5:= CreateEllipticRgn(0, 300, 200, 500);
r6:= CreateEllipticRgn(500, 40, 600, 140);
r7:= CreateEllipticRgn(540, 40, 640, 140);
//Комбинирование
//..разрезы в основном регионе
CombineRgn(r1, r1, r2, RGN_XOR);
CombineRgn(r1, r1, r3, RGN_XOR);
//..круглая "дырка" в левой стороне
CombineRgn(r1, r1, r4, RGN_XOR);
//..присоединение круга в левой нижней части
CombineRgn(r1, r1, r5, RGN_OR);
//..создание "дырки" в форме полумесяца