C# 确定最接近鼠标指针的控件
在我的C#(.NET2)应用程序中,我想确定哪个控件最靠近鼠标 我可以想出一些方法来做这件事,但这些方法不太管用。我可以使用C# 确定最接近鼠标指针的控件,c#,.net,winforms,graphics,controls,C#,.net,Winforms,Graphics,Controls,在我的C#(.NET2)应用程序中,我想确定哪个控件最靠近鼠标 我可以想出一些方法来做这件事,但这些方法不太管用。我可以使用控件.Location属性,但这只会让我看到上/左,鼠标可能在控件的另一侧。我可以计算控件的中心点,但大型控件会使其倾斜(接近控件的边缘视为接近控件) 基本上我在画布上有一堆矩形和一个点。我需要找到离点最近的矩形 (理想情况下,我也想知道点和矩形之间的距离) 有什么想法吗?你必须用矩形来思考:) 测试:鼠标在控制范围内吗 如果不是:离任何一条边有多远 然后您必须知道您感兴趣
控件.Location
属性,但这只会让我看到上/左,鼠标可能在控件的另一侧。我可以计算控件的中心点,但大型控件会使其倾斜(接近控件的边缘视为接近控件)
基本上我在画布上有一堆矩形和一个点。我需要找到离点最近的矩形
(理想情况下,我也想知道点和矩形之间的距离)
有什么想法吗?你必须用矩形来思考:)
然后您必须知道您感兴趣的控件,例如,表单是一个控件。首先,创建一个方法,该方法将计算从矩形边到某个任意点的距离。此方法的签名应为:
double DistanceFrom(Rect r, Point p);
然后,对于最简单的尝试,迭代所有控件,计算距离,记住最小距离和提供它的控件
对于矩形距离,请查看
编辑:
事实上,您可以维护一个已排序的控件列表,这样您就可以始终拥有第一个更靠近顶部的控件,并在鼠标移动时维护该列表-这可能证明在速度方面更有效。有趣的问题:)您需要找到以下内容:
-到最近拐角的距离
-到最近边缘的距离
-(可选)到中心的距离
基本上,您需要这三个值中的较小值。取两个控件的最小值,以确定哪个更接近 通过迭代表单上的所有控件并创建下面类的集合,在加载表单时开始 要找到离某个点最近的控件,请迭代该集合(请参见底部的代码)。以迄今为止发现的最小距离跟踪控制装置。如果需要,可以测试ContainsPoint()。。。如果您发现一个控制点落在控制边界内,那么您就拥有了控制点(只要没有重叠的控制点)。否则,当到达集合末尾时,找到的到中心/边缘距离最短的控件就是您的控件
public class HitControl {
public Control ThisControl;
private Rectangle ControlBounds;
private Point Center;
public HitControl (Control FormControl) {
ControlBounds = FormControl.Bounds;
Center = new Point(ControlBounds.X + (ControlBounds.Width/2), ControlBounds.Y + (ControlBounds.Height/2));
}
// Calculate the minimum distance from the left, right, and center
public double DistanceFrom(Point TestPoint) {
// Note: You don't need to consider control center points unless
// you plan to allow for controls placed over other controls...
// Then you need to test the distance to the centers, as well,
// and pick the shortest distance of to-edge, to-side, to-corner
bool withinWidth = TestPoint.X > ControlBounds.X && TestPoint.X < ControlBounds.X + ControlBounds.Width;
bool withinHeight = TestPoint.Y > ControlBounds.Y && TestPoint.Y < ControlBounds.Y + ControlBounds.Height;
int EdgeLeftXDistance = Math.Abs(ControlBounds.X - TestPoint.X);
int EdgeRightXDistance = Math.Abs(ControlBounds.X + ControlBounds.Width - TestPoint.X);
int EdgeTopYDistance = Math.Abs(ControlBounds.Y - TestPoint.Y);
int EdgeBottomYDistance = Math.Abs(ControlBounds.Y + ControlBounds.Height - TestPoint.Y);
int EdgeXDistance = Math.Min(EdgeLeftXDistance, EdgeRightXDistance);
int EdgeYDistance = Math.Min(EdgeTopYDistance, EdgeBottomYDistance);
// Some points to consider for rectangle (100, 100, 100, 100):
// - (140, 90): Distance to top edge
// - (105, 10): Distance to top edge
// - (50, 50): Distance to upper left corner
// - (250, 50): Distance to upper right corner
// - (10, 105): Distance to left edge
// - (140, 105): Distance to top edge
// - (105, 140): Distance to left edge
// - (290, 105): Distance to right edge
// - (205, 150): Distance to right edge
// ... and so forth
// You're within the control
if (withinWidth && withinHeight) {
return Math.Min(EdgeXDistance, EdgeYDistance);
}
// You're above or below the control
if (withinWidth) {
return EdgeYDistance;
}
// You're to the left or right of the control
if (withinHeight) {
return EdgeXDistance;
}
// You're in one of the four outside corners around the control.
// Find the distance to the closest corner
return Math.Sqrt(EdgeXDistance ^ 2 + EdgeYDistance ^ 2);
}
public bool ContainsPoint (Point TestPoint) {
return ControlBounds.Contains(TestPoint);
}
}
// Initialize and use this collection
List<HitControl> hitControls = (from Control control in Controls
select new HitControl(control)).ToList();
Point testPoint = new Point(175, 619);
double distance;
double shortestDistance = 0;
HitControl closestControl = null;
foreach (HitControl hitControl in hitControls) {
// Optional... works so long as you don't have overlapping controls
// If you do, comment this block out
if (hitControl.ContainsPoint(testPoint)) {
closestControl = hitControl;
break;
}
distance = hitControl.DistanceFrom(testPoint);
if (shortestDistance == 0 || distance < shortestDistance) {
shortestDistance = distance;
closestControl = hitControl;
}
}
if (closestControl != null) {
Control foundControl = closestControl.ThisControl;
}
公共类HitControl{
公共控制;公共控制;
私有矩形控制边界;
私人点中心;
公共控件(控件窗体控件){
ControlBounds=FormControl.Bounds;
中心=新点(ControlBounds.X+(ControlBounds.Width/2),ControlBounds.Y+(ControlBounds.Height/2));
}
//计算距离左侧、右侧和中心的最小距离
公共双距离(测试点){
/Note:你不需要考虑控制中心点,除非
//您计划允许将控件放置在其他控件之上。。。
//然后你还需要测试到中心的距离,
//并选择到边、到边、到角的最短距离
boolwithinwidth=TestPoint.X>ControlBounds.X&&TestPoint.XControlBounds.Y&&TestPoint.Y