2010-10-19 54 views
5

在我的C#(.NET 2)应用程序中,我想确定哪个控件最接近鼠标。确定哪个控件最接近鼠标指针

我可以想到一些方法来做到这一点,这不会很正常。我可以使用Control.Location属性,但这只是给我顶部/左侧,而鼠标可能位于控件的另一侧。我可以计算一个控件的中心点,但是大的控件会偏离这个(靠近控件的边缘计算为接近控件)。

所以基本上我有一堆画布和一个点的矩形。我需要找到离这个点最近的矩形。

(理想情况下,我想实际知道点和矩形之间的距离)。

任何想法?

+0

这些答案中的一个对你有帮助吗? – 2010-11-04 23:31:37

回答

3

你需要找到以下内容:
- 距离最近的角落
- 距离最接近的边缘
- (可选)到中心的距离

基本上,你希望这三个值中较小的一个。用两个控件的最小值来确定哪个更接近。

当您通过迭代窗体上的所有控件并在下面创建类的集合来加载窗体时开始。

要找到最接近某个点的控件,请迭代该集合(请参阅底部的代码)。使用迄今为止发现的最小距离跟踪控件。如果你想...你可以测试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; 
} 
0

你必须考虑在矩形:)

  1. 测试方面:是鼠标控制范围之内?
  2. 如果不是:距离任何单边有多远?

然后,你必须知道它控制你有兴趣,形式为,例如,一控制..

0

首先,创建方法,将计算从矩形边缘至某任意点的距离。签名这种方法应该是:

double DistanceFrom(Rect r, Point p); 

然后,最简单的尝试,遍历所有的控制,计算距离,remeber所提供它的最小距离和控制。

对于矩形距离,请检查this出。

编辑:

事实上,你可以保持控制排序列表,以便您可以总是有第一个是在顶部越近,并保持该列表作为移动鼠标 - 它可能被证明是更有效在速度方面。有趣的问题虽然:)

1

首先检查点是否在任何rectangle。如果不是,您可以使用this中的算法找到您的点和每个线段之间的距离。 您还可以找到控件的4个部分,因此您有一个包含四个部分(确定控制端)的列表(第一次启动),现在可以找到最近的部分,即其最近的矩形。

0

我同意丹尼尔说我们需要: double DistanceFrom(Rect r,Point p);

但是在此之前,我们需要: double DistanceFrom(Line r,Point p); 和 double AngleBetweenPoints(Point p1,Point p2);