How to Control Clipping and Window Shapes in Delphi Using Regions Guide to CreateRectRgn and CreateEllipticRgn
When you want to clip part of an image or freely change the shape of a window in Delphi, the Windows API Region functions are extremely useful.
This article explains how to create rectangular, elliptical, and polygonal regions using functions such as CreateRectRgn, CreateEllipticRgn, CreatePolygonRgn, and CreateRoundRectRgn, and how to apply them for clipping and window‑shape control.
These techniques are especially helpful for tasks such as:
- Clipping and copying only a specified region of an image
- Creating elliptical or polygonal windows for animation effects
- Combining multiple regions to build complex UI shapes
Sample code is included to walk you through the implementation in Delphi step by step.
API Functions for Creating Regions
The Windows API provides several functions for creating regions.
- CreateEllipticRgn(x1,y1, x2,y2:Integer):HRGN;
-
Creates an elliptical region inscribed within the rectangle defined by the top‑left point (x1, y1) and the bottom‑right point (x2, y2).
var Rgn:HRGN; begin Rgn:=CreateEllipticRgn(10,10,90,90); //Delete the region DeleteObject(Rgn); end; - CreatePolygonRgn(Points:Array of TPoint, Count:Integer, FillMode:Integer):HRGN;
-
Creates a polygonal region using the vertices specified in
Points.
Countspecifies the number of points (vertices).
FillModemust be one of the following values:Value Description ALTERNATE Fills the polygon using the even‑odd rule.
A point is considered inside if a ray drawn from that point to infinity crosses the polygon edges an odd number of times.WINDING Fills the polygon using the non‑zero winding rule.
A point is considered inside if the number of edge crossings is non‑zero.var Rgn:HRGN; Points: array[0..4] of TPoint; begin Points[0] := Point(90, 10); Points[1] := Point(10, 100); Points[2] := Point(120, 110); Points[3] := Point(10, 10); Points[4] := Point(60, 140); Rgn:=CreatePolygonRgn(Points,Length(Points),WINDING); //Delete the region DeleteObject(Rgn); end; - CreateRectRgn(x1,y1, x2,y2:Integer):HRGN;
-
Creates a rectangular region defined by the top‑left point (x1, y1) and the bottom‑right point (x2, y2).
var Rgn:HRGN; begin Rgn:=CreateRectRgn(10,10,90,90); //Delete the region DeleteObject(Rgn); end; - CreateRoundRectRgn(x1,y1, x2,y2, w,h:Integer):HRGN;
-
Creates a rounded‑rectangle region defined by the top‑left point (x1, y1) and the bottom‑right point (x2, y2), with corner ellipse width
wand heighth.
var Rgn:HRGN; begin Rgn:=CreateRoundRectRgn(10,10, 90,90, 10,6); //Delete the region DeleteObject(Rgn); end;
Combining Regions
You can combine two existing regions to create a new one.
To combine regions, use the CombineRgn function.
- CombineRgn(RgnDest, RgnSrc1,RgnSrc2:HRGN, iMode:Integer);
-
Creates a new region
RgnDestby combiningRgnSrc1andRgnSrc2using the mode specified iniMode.
iModecan be one of the following values:Value Description RGN_AND Creates the intersection (logical AND) of the two regions. RGN_COPY Copies RgnSrc1(ignoresRgnSrc2).RGN_DIFF Creates the part of RgnSrc1that is not overlapped byRgnSrc2.RGN_OR Creates the union (logical OR) of the two regions. RGN_XOR Creates the symmetric difference (logical XOR) of the two regions.
var Rgn1,Rgn2: HRGN; begin Rgn1:=CreateRoundRectRgn(10,10, 90,90, 10,6); Rgn2:=CreateEllipticRgn(50,50,140,140); //Combine Rgn1 and Rgn2 using OR, storing the result in Rgn1 CombineRgn(Rgn1,Rgn1,Rgn2,RGN_OR); //Delete regions DeleteObject(Rgn1); DeleteObject(Rgn2); end;
Creating a Test Application
Creating the Test Project and Designing the Form
Create a new project by selecting File → New → VCL Forms Application – Delphi.
From the Tool Palette in the lower‑right pane, drag and drop two TImage components and two TButton components onto the form (Form1).
Creating an Elliptical Region and Clipping the Image
Copy and paste the following source code into your project.
Set the OnClick event of Button1 to Button1Click,
and set the OnCreate event of Form1 to FormCreate.
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;
type
TForm1 = class(TForm)
Image1: TImage;
Image2: TImage;
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
Bmp1,Bmp2:TBitmap;
Rgn1: HRGN;
begin
Bmp1:=Image1.Picture.Bitmap;
Bmp2:=Image2.Picture.Bitmap;
//Create an elliptical region (x1, y1, x2, y2)
Rgn1:=CreateEllipticRgn(30, 50, 170, 150);
//Set the region as the clipping area
SelectClipRgn(Bmp2.Canvas.Handle, Rgn1);
//Draw Image1.Picture.Bitmap onto Image2.Picture.Bitmap
Bmp2.Canvas.Draw(0,0,Bmp1);
//Delete the region
DeleteObject(Rgn1);
//Clear the clipping region
SelectClipRgn(Bmp2.Canvas.Handle, 0);
end;
procedure TForm1.FormCreate(Sender: TObject);
var Bmp1,Bmp2:TBitmap;
begin
Image1.Width:=200;
Image1.Height:=200;
Bmp1:=Image1.Picture.Bitmap;
Bmp1.SetSize(Image1.Width,Image1.Height);
Image2.Width := Image1.Width;
Image2.Height := Image1.Height;
Bmp2:=Image2.Picture.Bitmap;
Bmp2.Width:=Image1.Width;
Bmp2.Height:=Image1.Height;
//Draw something on Image1.Picture.Bitmap
Bmp1.Canvas.Brush.Color:=clWhite;
Bmp1.Canvas.FillRect(bmp1.Canvas.ClipRect);
Bmp1.Canvas.Brush.Color:=clGreen;
Bmp1.Canvas.FillRect(Rect(50,50,150,150));
Bmp1.Canvas.Pen.Width:=4;
Bmp1.Canvas.Pen.Color:=clBlue;
Bmp1.Canvas.MoveTo(0,0);
Bmp1.Canvas.LineTo(Bmp1.Width,Bmp2.Height);
Bmp1.Canvas.Pen.Color:=clYellow;
Bmp1.Canvas.MoveTo(Bmp1.Width,0);
Bmp1.Canvas.LineTo(0,Bmp2.Height);
//Fill Image2.Picture.Bitmap with red
Bmp2.Canvas.Brush.Color:=clRed;
Bmp2.Canvas.FillRect(bmp2.Canvas.ClipRect);
end;
Click Run → Run to execute the application.
When you click Button1, you will see that only the elliptical area
(30, 50, 170, 150) of Image1 has been copied into Image2.
Setting the Window Shape to Match a Region
To change the shape of a window (its window region) to match a region, use the SetWindowRgn API function.
- SetWindowRgn(hWnd:HWND; hRgn:HRGN; bRedraw:LongBool):HRGN;
-
Sets the window region of the window whose handle is
hWndtohRgn.
IfbRedrawis True, the window is redrawn.
var Rgn:HRGN; begin Rgn:=CreateRoundRectRgn(10,10, 900,900, 20,30); //Set the window shape to match the region SetWindowRgn(Self.Handle, Rgn1, True); //Delete the region DeleteObject(Rgn); end;
Double‑click Button2 and enter the following source code.
procedure TForm1.Button2Click(Sender: TObject); var Points: array[0..3] of TPoint; Rgn1,Rgn2: HRGN; begin //Polygon points Points[0] := Point(0, 0); Points[1] := Point(Self.Width, 0); Points[2] := Point(Self.Width, Self.Height div 3 * 2); Points[3] := Point(0, Self.Height div 2); //Create a polygon region Rgn1:=CreatePolygonRgn(Points,Length(Points),WINDING); //Create a rectangular region (example) //Rgn2:=CreateRectRgn(100, 100, 180, 180); //Create an elliptical region Rgn2:=CreateEllipticRgn(0, Self.Height div 2, Self.Width div 2, Self.Height); //Combine Rgn1 and Rgn2 using OR, storing the result in Rgn1 CombineRgn(Rgn1,Rgn1,Rgn2,RGN_OR); //Set the window shape to match the region SetWindowRgn(Self.Handle, Rgn1, True); //Delete regions DeleteObject(Rgn1); DeleteObject(Rgn2); end;
Click Run → Run to execute the application.
When you click Button2, the window shape will change.
To reset the window region, use the following:
SetWindowRgn(Self.Handle, 0, True);
Animating the Window Shape at Application Startup Using a Region
To animate the window when the application starts, add the following source code to the OnActivate event of TForm1.
procedure TForm1.FormActivate(Sender: TObject);
var RectRgn: HRGN;
i:Integer;
begin
for i := 0 to 50 do
begin
//Create a rectangular region within the specified range
RectRgn := CreateRectRgn(
Width div 2 - Width * i div 100,
Height div 2 - Height * i div 100,
Width div 2 + Width * i div 100,
Height div 2 + Height * i div 100
);
//Apply the region to the form's window
SetWindowRgn(Handle, RectRgn, True);
//Release the created region object
DeleteObject(RectRgn);
//Wait 10 ms to smooth the animation
Sleep(10);
//Process pending UI messages
Application.ProcessMessages;
end;
//Reset the region and restore the original window shape
SetWindowRgn(Handle, 0, True);
end;
