I want to use regions on a Canvas
to detect the mouse moving over them, but I can't manage to get CreatePolygonRgn()
working properly.
Here is a sample code:
var
regs : array of HRGN;
procedure TForm8.Button1Click(Sender: TObject);
var
n : integer;
p : array[0..3] of integer;
begin
SetLength(regs, 10);
for n := 1 to Length(regs) do try
p[0] := n*50-20;
p[1] := n*50+20;
p[2] := n*50+20;
p[3] := n*50-20;
regs[n-1] := CreatePolygonRgn(p[0], 2 {neither with 4}, 1); // seems not working as expected
// regs[n-1] := CreateRectRgn(p[0], p[1], p[2], p[3]); // this works
FillRgn(image.Canvas.Handle, regs[n-1], image.Canvas.Brush.Handle); // doesn't draw anything
except
ShowMessage('error creating region');
end;
Application.ProcessMessages;
end;
procedure TForm8.ImageMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
if (ssCtrl in Shift) then begin
for var i : integer := 0 to Length(regs)-1 do
if PtInRegion(regs[i], X, Y) then begin // works only with CreateRectRgn
ShowMessage('region ' + IntToStr(i));
break;
end;
end;
end;
What I am doing wrong?
EDIT
The following test code works fine. But the exactly same code in my real application doesn't ! On the ImageClick event the function PtInRegion raises the exception "Range check error" for SOME of regions, NOT ALL of them (different on different runs), but paints the regions as expected when I comment out this function! For me this means that the region's bounds are right and while the mouse is inside the region, ptInRegion raises the exception. This behavior doesn't exist with the sample code and drives me crazy!
unit Unit8;
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
TForm8 = class(TForm)
Image: TImage;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure ImageClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form8: TForm8;
implementation
{$R *.dfm}
var regs : array of HRGN;
procedure TForm8.Button1Click(Sender: TObject);
var n : integer;
var p : array[0..3] of TPoint;
begin
for n := 0 to length(regs)-1 do
if regs[n] > 0 then
DeleteObject(regs[n]); // delete existing regions
setLength(regs,10);
n := 0;
for n := 0 to 9 do try
p[0].X := 50*n-20;
p[0].Y := 50*n+20;
p[1].X := 50*n-20;
p[1].Y := 50*n-20;
p[2].X := 50*n+20;
p[2].Y := 50*n-20;
p[3].X := 50*n+20;
p[3].Y := 50*n+20;
regs[n] := CreateRectRgn(p[0].X,p[0].Y,p[2].X,p[2].Y);
//regs[n] := CreatePolygonRgn(p[0],4,WINDING);
image.Canvas.Brush.Color := clYellow;
PaintRgn (image.canvas.Handle,regs[n]);
image.Canvas.Brush.Color := clBlue;
FrameRgn(image.canvas.Handle,regs[n],image.Canvas.Brush.Handle,1,1);
except
showmessage('error');
end;
image.Invalidate;
end;
procedure TForm8.ImageClick(Sender: TObject);
begin
var p : TPoint := image.ScreenToClient(mouse.cursorPos);
for var i : integer := 0 to length(regs)-1 do
if PtInRegion(regs[i],p.X,p.Y) then begin
image.Canvas.Brush.color := clGreen;
paintRgn(image.canvas.Handle,regs[i]);
image.Canvas.Brush.color := clRed;
FrameRgn(image.canvas.Handle,regs[i],image.Canvas.Brush.Handle,1,1);
image.Canvas.Brush.color := clYellow;
image.Canvas.TextOut(p.x,p.y,intToStr(i));
break;
end;
end;
end.