如何定义三角形等不规则屏幕区域并检测鼠标是否位于该区域内
检测鼠标是否在任意多边形/自定义区域内的实现方案
你可以直接用下面两种成熟方案实现,从简单的三角形到任意复杂多边形都能覆盖:
方案1:通用多边形点检测算法(跨平台可用)
最常用的是射线交叉法,原理是从待检测点向水平右侧发射一条虚拟射线,统计射线和多边形边的交点数量:奇数代表点在多边形内部,偶数代表在外部。
Pascal实现代码如下:
type TPointArray = array of TPoint; // 判断点pt是否在多边形polygon内 function PtInPolygon(const pt: TPoint; const polygon: TPointArray): Boolean; var i, j: Integer; intersect: Boolean; begin Result := False; j := High(polygon); for i := Low(polygon) to High(polygon) do begin // 检测当前边和水平射线是否相交 if ((polygon[i].Y > pt.Y) <> (polygon[j].Y > pt.Y)) then begin intersect := (pt.X < (polygon[j].X - polygon[i].X) * (pt.Y - polygon[i].Y) / (polygon[j].Y - polygon[i].Y) + polygon[i].X); if intersect then Result := not Result; end; j := i; end; end;
使用的时候只需要把三角形的三个顶点按顺序放进TPointArray,再传入鼠标坐标即可:
var triangle: TPointArray; mousePos: TPoint; begin SetLength(triangle, 3); // 替换为你自己的三角形三个顶点坐标 triangle[0] := Point(100, 100); triangle[1] := Point(200, 100); triangle[2] := Point(150, 200); mousePos := Mouse.CursorPos; if PtInPolygon(mousePos, triangle) then begin // 鼠标在三角形内的逻辑 end; end;
方案2:Windows平台原生API实现(更简单,支持复杂区域)
如果你的程序只跑在Windows上,直接用GDI的区域API即可,系统已经封装好了所有判断逻辑,还支持多边形、椭圆、矩形合并等复杂形状:
uses Windows; var rgn: HRGN; trianglePts: array[0..2] of TPoint; mousePos: TPoint; begin // 填充三角形三个顶点 trianglePts[0] := Point(100, 100); trianglePts[1] := Point(200, 100); trianglePts[2] := Point(150, 200); // 创建多边形区域,最后一个参数是填充模式,ALTERNATE就够用 rgn := CreatePolygonRgn(trianglePts, 3, ALTERNATE); try mousePos := Mouse.CursorPos; if PtInRegion(rgn, mousePos.X, mousePos.Y) then begin // 鼠标在区域内的逻辑 end; finally // 用完一定要删除区域,避免GDI资源泄漏 DeleteObject(rgn); end; end;
如果要做更复杂的形状,还可以用CombineRgn把多个矩形、椭圆、多边形区域合并成一个整体再检测。
小提示:如果是不规则的任意位图形状,可以先创建对应掩码的区域再用
PtInRegion检测,不需要自己写碰撞算法。
内容的提问来源于stack exchange,提问作者Codrut
相关产品推荐
相关产品推荐

