Regiony



Wielu początkujących programistów zastanawia się jak wykonać przycisk w kształcie gwiazdy, który reaguje na kliknięcie tylko w rejonie tego kształtu. Do tego celu służą regiony. W Windowsie region jest kwadratem, polygonem(dowolnym kształtem) lub elipsą (lub kombinacją dwóch lub większej liczby tych kształtów), które mogą być wypełnione, pomalowane, odwrócone, obramowane i użyte do wykrywania kolizji (pozycji kursora). Aplikacja tworzy region poprzez wywołanie funkcji powiązanej ze specyficznym kształtem. Poniżej przedstawione są funkcje powiązane ze wszystkimi standardowymi kształtami:

kwadrat: CreateRectRgn, CreateRectRgnIndirect
kwadrat z zaokrąglonymi narożnikami: CreateRoundRectRgn
elipsa: CreateEllipticRgn, CreateEllipticRgnIndirect
polygon: CreatePolygonRgn, CreatePolyPolygonRgn

Aplikacja łączy dwa regiony poprzez wywołanie funkcji CombineRgn. Istnieje pięć możliwości łączeń regionów:

RGN_AND: skrzyżowane części dwóch regionów tworzą nowy region
RGN_COPY: kopia pierwszego (z dwóch oryginalnych regionów) tworzy nowy region
RGN_DIFF: część pierwszego regionu, która nie krzyżuje się z drugim, tworzy nowy region
RGN_OR: dwa oryginalne regiony tworzą nowy region
RGN_XOR: te części dwóch oryginalnych regionów, które się nie pokrywają, tworzą nowy region

Poniższe ilustracje pokazują wynik połączenia regionów (kwadratowego i okrągłego) pięcioma możliwymi funkcjami:


Przejdziemy do przykładów. Na początek stworzymy kwadrat, koło i narysujemy tekst.
var
  x0, y0: Integer; 
  rgn1, rgn2, rgn3: HRGN;
begin
  x0 := 20; y0 := 20; // kwadrat 
  rgn1 := CreateRectRgn(x0, y0, x0 + 130, y0 + 30);
  x0 := 200; y0 := 30; // koło
  rgn2 := CreateEllipticRgn(x0, y0, x0 + 60, y0 + 60);
  x0 := 70; y0 := 90; // tekst
  BeginPath(Canvas.Handle);
  Canvas.Brush.Style := bsClear;
  Canvas.Font.Name := 'Times New Roman';
  Canvas.Font.Size := 90;
  Canvas.Font.Style := [fsBold];
  Canvas.TextOut(260, 80, 'A');
  EndPath(Canvas.Handle);
  rgn3 := PathToRegion(Canvas.Handle);
end;
Teraz stworzymy bardziej złożony region poprzez połączenie trzech regionów:
var
  x0, y0 :integer;
  rgn0, rgn1, rgn2, rgn3:HRGN;
begin
  rgn0 := CreateRectRgn(x0, y0, x0 + 130, y0 + 40); // utworzenie nowego       regionu
  rgn1 := CreateRectRgn(x0, y0 + 80,x0 + 130, y0 + 100); // utworzenie trzech regionów które będą złączone
  rgn2 := CreateEllipticRgn(x0 + 5, y0 + 30, x0 + 30, y0 + 90);
  rgn3 := CreateEllipticRgn(x0 + 100, y0 + 30, x0 + 125, y0 + 90);
  CombineRgn(rgn0, rgn0, rgn1, RGN_OR); // połączenie ich w jeden     region
  CombineRgn(rgn0, rgn0, rgn2, RGN_OR);
  CombineRgn(rgn0, rgn0, rgn3, RGN_OR);
  DeleteObject(rgn1); // usunięcie ich z pamięci
  DeleteObject(rgn2);
  DeleteObject(rgn3);
Do tworzenia bardziej złożonych regionów służy także komenda CreatePolygonRgn. Do zmiany kształtu formy służy funkcja SetWindowRgn. Wykorzystamy obie te funkcje do stworzenia formy w kształcie pięcioramiennej gwiazdy:

procedure TForm1.FormCreate(Sender: TObject); // tworzenie kształtu odbywa się podczas tworzenia formy
var
  punkty: array[0..10] of TPoint; // tablica zawierająca wierzchołki, potrzebna do zainicjowania funkcji CreatePolygonRgn
begin
  punkty[0] := Point(162,0); // współrzędne wierzchołków gwiazdy
  punkty[1] := Point(202,117);
  punkty[2] := Point(325,117);
  punkty[3] := Point(225,192);
  punkty[4] := Point(263,308);
  punkty[5] := Point(162,236);
  punkty[6] := Point(62,308);
  punkty[7] := Point(100,191);
  punkty[8] := Point(0,117);
  punkty[9] := Point(124,117);
  punkty[10] := Point(162,0);
  SetWindowRgn(Handle, CreatePolygonRgn(punkty, 11, WINDING), True); // utworzenie formy w kształcie gwiazdy
end;





...powrót