I need to find the control under the mouse, within an event of another control. I could start with GetTopLevel
and iterate down using GetChildAtPoint
, but is there a quicker way?
views:
438answers:
3
+1
A:
Untested and off the top of my head (and maybe slow...):
Control GetControlUnderMouse() {
foreach ( Control c in this.Controls ) {
if ( c.Bounds.Contains(this.PointToClient(MousePosition)) ) {
return c;
}
}
Or to be fancy with LINQ:
return Controls.Where(c => c.Bounds.Contains(PointToClient(MousePosition))).FirstOrDefault();
I'm not sure how reliable this would be, though.
Lucas Jones
2009-02-25 17:37:08
I just used this, it's great to get *every* control under a mouse position. However, it should be c.Bounds.Contains(Point p) not c.Bounds.IntersectsWith(Rectangle r).
snicker
2009-10-19 22:54:34
D'oh! Thanks. I'll just edit it now...
Lucas Jones
2009-10-20 07:07:26
+3
A:
This code doesn't make a lot of sense, but it does avoid traversing the Controls collections:
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr WindowFromPoint(Point pnt);
private void Form1_MouseMove(object sender, MouseEventArgs e) {
IntPtr hWnd = WindowFromPoint(Control.MousePosition);
if (hWnd != IntPtr.Zero) {
Control ctl = Control.FromHandle(hWnd);
if (ctl != null) label1.Text = ctl.Name;
}
}
private void button1_Click(object sender, EventArgs e) {
// Need to capture to see mouse move messages...
this.Capture = true;
}
Hans Passant
2009-02-25 17:59:09
i might use that myself :)... It doesn't work in Mono/Linux though :(.
Lucas Jones
2009-02-25 19:12:52
Makes perfect sense to me. :-) WindowFromPoint grabs the window handle directly under the mouses position on the screen, regardless of containment. Control.FromHandle translates it into a .Net control (if possible). Boom, done. Very slick.
Jason D
2010-03-11 14:25:46