我正在Delphi中创建一个自定义控件(继承自TCustomControl
),它包含许多多边形列表项(不规则形状)。我需要为每个项目实现鼠标事件,但首先我需要能够检测鼠标位置是否在给定的多边形(array of TPoint
)内。我正在捕获命中测试消息(WM_NCHITTEST
),这是我需要进行此验证的地方。我有许多多边形,我将遍历每个多边形项并执行此检查以查看鼠标的X / Y位置是否在此多边形内。
procedure TMyControl.WMNCHitTest(var Message: TWMNCHitTest);
var
P: TPoint; //X/Y of Mouse
Poly: TPoints; //array of TPoint
X: Integer; //iterator
I: TMyListItem; //my custom list item
begin
P.X:= Message.XPos;
P.Y:= Message.YPos;
for X := 0 to Items.Count - 1 do begin
I:= Items[X]; //acquire my custom list item by index
Poly:= I.Points; //acquire polygon points
//Check if Point (P) is within Polygon (Poly)...?
end;
end;
答案 0 :(得分:15)
您可以使用PtInRegion
:
function PointInPolygon(Point: TPoint; const Polygon: array of TPoint): Boolean;
var
rgn: HRGN;
begin
rgn := CreatePolygonRgn(Polygon[0], Length(Polygon), WINDING);
Result := PtInRegion(rgn, Point.X, Point.Y);
DeleteObject(rgn);
end;
答案 1 :(得分:5)
您可以使用此处的光线投射算法:http://en.wikipedia.org/wiki/Point_in_polygon#Ray_casting_algorithm
大多数计算机图形类都以此为例。
答案 2 :(得分:1)
检查点是否在多边形内部可以通过想象通过该点的水平线,然后从左到右计算该想象线穿过多边形的次数来完成。如果在点击点之前多边形交叉的数量是奇数,则点在内部,如果即使那么点在多边形之外。
答案 3 :(得分:0)
还有另一种我们广泛使用的技术,它根本不涉及任何数学,并且可以处理任何形状的极其复杂的嵌入式控制。只需要一个屏幕外的控件图像,所有部件都有颜色编码(如下图所示),用户可以点击。
当他们移动鼠标时,只需在我们的屏幕外图像中查看鼠标下方像素的颜色,并告诉我们他们究竟是什么按钮/控制 - 白色不是它,以及任何系列各种颜色的颜色。
//伪代码
function MouseOverControl(LocalMousePos:TPoint):ControlID;
begin
//sanity check
Result:=IDNull;
if (LocalMouse.X < 0) or (LocalMouse.X > ControlWidth) or
(LocalMouse.Y < 0) or (LocalMouse.Y > ControlHeight) then
exit;
case OffScreenControlMask.Canvas.Pixels[LocalMousePos.X,LocalMousePos.Y] of
clwhite:exit;
clRed:result:=ControlIDOne;
clGreen:result:=ControlIDTwo;
clBlue:result:=ControlIDThree;
... etc
end;
end;
注意:附加的颜色蒙版图像代表五个相同的圆形控件,分为带有中心按钮的象限(因为它们都使用相同的颜色,我们对每种颜色都有常量,我们确定鼠标中五个中的哪一个结束通过一个简单的XPosition)以及右边的一个额外的不规则控制和下面的一组或矩形按钮。