2009-02-25 4 views
11

Мне нужно найти элемент управления под мышью в случае другого элемента управления. Я мог бы начать с GetTopLevel и итерации вниз, используя GetChildAtPoint, но есть ли более быстрый способ?Есть ли быстрый способ получить элемент управления под мышкой?

+0

Почему нужно начинать с GetTopLevel, не могли бы вы просто пойти GetChildAtPoint напрямую? –

+0

(a) Элемент управления под мышью не обязательно является дочерним элементом элемента управления, событие которого стреляет, и (б) мне все равно придется итерировать, чтобы найти самый внутренний элемент управления. – Simon

ответ

16

Этот код не делает много смысла, но это избежать обхода элементов управления коллекции:

[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; 
} 
+0

Имеет для меня прекрасный смысл. :-) WindowFromPoint захватывает дескриптор окна непосредственно под положением мыши на экране, вне зависимости от сдерживания. Control.FromHandle переводит его в .Net-элемент управления (если возможно). Бум, сделано. Очень гладкий. –

+0

Не было бы проще имитировать щелчок мышью? Вы можете найти ссылку [здесь] (http://stackoverflow.com/questions/2416748/how-to-simulate-mouse-click-in-c) – Pimenta

+0

Что делать, если я хочу получить контроль над другим приложением & –

2

Непроверенные и от верхней части головы (и, возможно, медленно ...):

Control GetControlUnderMouse() { 
    foreach (Control c in this.Controls) { 
     if (c.Bounds.Contains(this.PointToClient(MousePosition))) { 
      return c; 
     } 
    } 
} 

Или быть фантазии с помощью LINQ:

return Controls.Where(c => c.Bounds.Contains(PointToClient(MousePosition))).FirstOrDefault(); 

Я не уверен, насколько надежен этот было бы, однако.

+0

Я просто использовал это, здорово получить * каждый * элемент управления под мышью. Однако это должно быть c.Bounds.Contains (Point p) not c.Bounds.IntersectsWith (Rectangle r). – snicker

+0

D'oh! Благодарю. Теперь я просто отредактирую его ... –

+0

это не работает со мной .. Я всегда получаю верхний контроль – SolidSnake