На рис. 1.8 явно видно, как в «дырках» формы просвечивает одно из окон среды разработки Delphi. При этом, когда указатель находится над «дыркой», сообщения от мыши получают те окна, части которых видны в «дырке».
Программный код, приводящий к созданию формы столь необычного вида, приведен в листинге 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.
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);
//..создание "дырки" в форме полумесяца
CombineRgn(r7, r7, r6, RGN_DIFF);
CombineRgn(r1, r1, r7, RGN_XOR);
formRgn:= CreateRectRgn(0, 0, 0, 0);
CombineRgn(formRgn, r1, 0, RGN_COPY);
DeleteObject(r1);
DeleteObject(r2);
DeleteObject(r3);
DeleteObject(r4);
DeleteObject(r5);
DeleteObject(r6);
DeleteObject(r7);
//Создание круглой кнопки закрытия
butRgn:= CreateEllipticRgn(50, 50, 150, 150);
SetWindowRgn(Button1.Handle, butRgn, False);
SetWindowRgn(Handle, formRgn, True);
end;
В этом листинге подписано, какие операции предназначены для создания каких элементов итогового региона. В операциях участвуют семь регионов. Расположение используемых в операциях регионов показано на рис. 1.10.
Рис. 1.10. Элементарные регионы, используемые для получения формы, представленной на рис. 1.9
Предыдущий пример наглядно демонстрирует мощь функции CombineRgn при построении регионов сложной формы. Однако существует огромное количество предметов, контуры которых крайне сложно повторить, комбинируя простые регионы. Построение многоугольных регионов с большим количеством точек может в этом случае выручить, но ведь это крайне нудно и утомительно.
Если есть изображение предмета, контуры которого должны совпадать с контурами региона, то гораздо проще при построении региона обрабатывать само изображение, выбирая все точки, для которых выполняется определенное условие. Используемое изображение и будет тем шаблоном, по которому «вырезается» регион нужной формы.