Как определить, находится ли мышь внутри всей формы и дочерних элементов управления?

Мне нужно определить, когда пользователь перемещает мышь поверх формы и всех ее дочерних элементов управления, а также когда она покидает форму. Я пробовал события MouseEnter и MouseLeave формы, я пробовал пары сообщений WM_MOUSEMOVE & WM_MOUSELEAVE и WM_NCMOUSEMOVE & WM_NCMOUSELEAVE сообщений Windows, но никто не работает так, как я хочу …

Большая часть моей Формы занята дочерними элементами управления многих видов, там мало видимой области клиента. Это означает, что если я двигаю мышь очень быстро, движение мыши не будет обнаружено, хотя мышь находится внутри Формы.

Например, у меня есть TextBox, который стыкуется внизу и между рабочим столом и TextBox, есть только очень маленькая граница. Если я быстро перемещу мышь снизу в TextBox, движение мыши не будет обнаружено, но мышь внутри TextBox, следовательно, внутри формы.

Как я могу достичь того, что мне нужно?

Вы можете подключить основной цикл сообщения и препроцесс / постпроцесс любого сообщения (WM_MOUSEMOVE), что вы хотите.

 public class Form1 : Form { private MouseMoveMessageFilter mouseMessageFilter; protected override void OnLoad( EventArgs e ) { base.OnLoad( e ); this.mouseMessageFilter = new MouseMoveMessageFilter(); this.mouseMessageFilter.TargetForm = this; Application.AddMessageFilter( this.mouseMessageFilter ); } protected override void OnClosed( EventArgs e ) { base.OnClosed( e ); Application.RemoveMessageFilter( this.mouseMessageFilter ); } class MouseMoveMessageFilter : IMessageFilter { public Form TargetForm { get; set; } public bool PreFilterMessage( ref Message m ) { int numMsg = m.Msg; if ( numMsg == 0x0200 /*WM_MOUSEMOVE*/) { this.TargetForm.Text = string.Format( "X:{0}, Y:{1}", Control.MousePosition.X, Control.MousePosition.Y ); } return false; } } } 

Как насчет этого: в OnLoad вашей формы рекурсивно просматривайте все дочерние элементы управления (и их дочерние элементы) и подключайте событие MouseEnter.

Затем всякий раз, когда мышь входит в любой потомок, вызывается обработчик событий. Аналогично, вы можете подключить события MouseMove и / или MouseLeave.

 protected override void OnLoad() { HookupMouseEnterEvents(this); } private void HookupMouseEnterEvents(Control control) { foreach (Control childControl in control.Controls) { childControl.MouseEnter += new MouseEventHandler(mouseEnter); // Recurse on this child to get all of its descendents. HookupMouseEnterEvents(childControl); } } 

В вашем пользовательском элементе управления создайте событие mousehover для вашего элемента управления (или другого типа события), подобное этому

 private void picBoxThumb_MouseHover(object sender, EventArgs e) { // Call Parent OnMouseHover Event OnMouseHover(EventArgs.Empty); } 

На вашем WinFrom, на котором размещены UserControl, есть это для UserControl для управления MouseOver в вашем Designer.cs

 this.thumbImage1.MouseHover += new System.EventHandler(this.ThumbnailMouseHover); 

Что вызывает этот метод на вашем WinForm

 private void ThumbnailMouseHover(object sender, EventArgs e) { ThumbImage thumb = (ThumbImage) sender; } 

Где ThumbImage – это тип пользовательского контроля

Быстрое и грязное решение:

 private bool MouseInControl(Control ctrl) { return ctrl.Bounds.Contains(ctrl.PointToClient(MousePosition)); }