¿Cómo detectar si el mouse está dentro de todo el formulario y los controles secundarios?

Necesito detectar cuándo el usuario mueve el mouse sobre el formulario y todos sus controles secundarios y también cuando abandona el formulario. MouseLeave eventos MouseEnter y MouseLeave del formulario, probé los pares de mensajes de Windows WM_MOUSEMOVE & WM_MOUSELEAVE y WM_NCMOUSEMOVE & WM_NCMOUSELEAVE pero ninguno parece funcionar como deseo …

La mayor parte de mi formulario está ocupado por controles secundarios de muchos tipos, no hay mucha área de clientes visible. Esto significa que si muevo el mouse muy rápidamente, el movimiento del mouse no se detectará, aunque el mouse esté dentro del Formulario.

Por ejemplo, tengo un TextBox que está acoplado en la parte inferior y entre el escritorio y el TextBox, solo hay un borde muy pequeño. Si muevo rápidamente el mouse desde la parte inferior al TextBox, el movimiento del mouse no se detectará, pero el mouse está dentro del TextBox, por lo tanto, dentro del formulario.

¿Cómo puedo lograr lo que necesito?

    Puede enlazar el bucle de mensajes principal y preprocesar / postprocesar cualquier mensaje (WM_MOUSEMOVE) que desee.

     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; } } } 

    ¿Qué tal esto? En el OnLoad de su formulario, recursivamente recorre todos los controles secundarios (y sus hijos) y conecte el evento MouseEnter.

    Luego, cuando el mouse ingrese a cualquier descendiente, se llamará al controlador de eventos. Del mismo modo, puede conectar eventos MouseMove y / o 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); } } 

    En su control de usuario, cree un evento de mousehover para su control como este, (u otro tipo de evento) como este

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

    En su WinFrom, donde se aloja el UserControl, tiene esto para que UserControl maneje el MouseOver en su Designer.cs

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

    Que llama a este método en su WinForm

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

    Donde ThumbImage es el tipo de control de usuario.

    Solución rápida y sucia:

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