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?
Asked
Active
Viewed 1.4k times
14

Simon
- 25,468
- 44
- 152
- 266
-
Why do you need to start at GetTopLevel, couldn't you simply go to GetChildAtPoint directly? – Marcus L Feb 25 '09 at 15:35
-
(a) The control under the mouse isn't necessarily a child of the control whose event is firing, and (b) I would still have to iterate down to find the innermost control. – Simon Feb 25 '09 at 15:36
2 Answers
21
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
- 922,412
- 146
- 1,693
- 2,536
-
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 Mar 11 '10 at 14:25
-
Would it not be easier to simulate the mouse click? You can find a link [here](http://stackoverflow.com/questions/2416748/how-to-simulate-mouse-click-in-c) – Pimenta Oct 24 '12 at 17:32
-
-
POINT pt; HWND hwnd; GetCursorPos (&pt); //find the control or window that lies underneath the mouse cursor. hwnd= WindowFromPoint (pt); – MathArt Oct 27 '21 at 07:03
2
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
- 19,767
- 8
- 75
- 88
-
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 Oct 19 '09 at 22:54
-
`MousePosition` will return a new `point` at each call which is not good for performance, it is better to cache that or better `PointToClient(MousePosition)` into a variable in your loop – S.Serpooshan Sep 25 '18 at 10:02