2009-06-12 17 views
7

Necesito detectar cuando el usuario mueve el mouse sobre el formulario y todos sus controles secundarios y también cuando abandona el formulario. Probé los MouseEnter y MouseLeave eventos del formulario, probé el WM_MOUSEMOVE & WM_MOUSELEAVE y WM_NCMOUSEMOVE & WM_NCMOUSELEAVE pares de mensajes de ventanas, pero ninguno parece funcionar como quiero ...¿Cómo detectar si el mouse está dentro de todo el formulario y controles secundarios?

mayor parte de mi forma es ocupada por los controles secundarios de muchos tipos, no hay mucho área de cliente 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 cuadro de texto que se acopla en la parte inferior y entre el escritorio y el cuadro de texto, sólo hay una pequeña frontera. Si muevo el mouse rápidamente de la parte inferior al TextBox, no se detectará el movimiento del mouse, pero el mouse está dentro del TextBox, por lo tanto, dentro del Formulario.

¿Cómo puedo lograr lo que necesito?

Respuesta

13

Puede enlazar el mensaje principal de bucle y postproceso alguno (WM_MOUSEMOVE) Mensaje de preproceso/lo que quiere.

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

    } 
} 
+0

Eso sólo hace que funcione a la inversa ... Es decir, ahora se detecta cuando el ratón está sobre el Formulario de controles secundarios, pero no la forma en sí. Quiero detectar TODO. También necesito detectar cuándo el mouse entró al Formulario y cuándo se fue, no solo que se está moviendo hacia adentro. –

+0

Bueno, he encontrado exactamente lo que estaba buscando en este ejemplo: http://netcode.ru/dotnet/?lang=&katID=30&skatID=283&artID=7862. Utiliza el mismo principio que tu respuesta, el IMessageFilter. Y me permite detectar cuando el mouse entra y sale del formulario. Solo tengo que adaptar y quitar el código a lo que quiero. De todos modos, si pudiera elaborar su respuesta en el IMessageFilter, qué es, cómo funciona y todo eso, marcaré esta respuesta como la aceptada. Y por favor agregue una nota para verificar los comentarios de otras personas que buscan una solución al mismo problema. –

+0

¿Viste mi solicitud TcKS? Tal vez lo hagas esta vez ... ¿Podrías editar tu publicación y elaborar un poco sobre el tema completo de IMessageFilter y cómo funciona? –

2

¿Qué tal esto: En OnLoad de su forma, de manera recursiva pasar por todos los controles secundarios (y sus hijos) y conectar el evento MouseEnter.

A continuación, cada vez que el ratón entra en cualquier descendiente, se llamará al controlador de eventos. Del mismo modo, puede conectar los 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); 
    } 
} 
+0

Yo llamaría eso una "solución alternativa" y no la solución, entonces no ... –

+0

No funcionará cuando los controles cambien durante la vida del formulario. – TcKs

0

En el control de usuario crear un evento MouseHover para el control de este tipo, (u otro tipo de evento) como esto

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

En su WinFrom que alberga el control de usuario tiene esto para el control de usuario para manejar la 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; 

} 

Dónde ThumbImage es el tipo de usercontrol

0

solución rápida y sucia:

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