2009-06-12 6 views
7

Devo rilevare quando l'utente sposta il mouse sopra il modulo e tutti i relativi controlli figlio e anche quando lascia il modulo. Ho provato le MouseEnter e MouseLeave eventi del modulo, ho provato la WM_MOUSEMOVE & WM_MOUSELEAVE e WM_NCMOUSEMOVE & WM_NCMOUSELEAVE coppie di messaggi di Windows, ma nessuno sembra funzionare come voglio ...Come rilevare se il mouse si trova nell'intero modulo e nei controlli figlio?

La maggior parte della mia forma è occupato da controlli figlio di molti tipi, non c'è molta area cliente visibile. Ciò significa che se muovo il mouse molto velocemente, il movimento del mouse non verrà rilevato, sebbene il mouse si trovi all'interno del modulo.

Per esempio, ho un TextBox che è ancorata sul fondo e tra il desktop e il controllo TextBox, c'è solo un piccolo bordo. Se sposto rapidamente il mouse dal fondo nel TextBox, il movimento del mouse non verrà rilevato, ma il mouse si trova all'interno del TextBox, quindi all'interno del modulo.

Come posso ottenere ciò di cui ho bisogno?

risposta

13

È possibile agganciare il ciclo di messaggi principale e post elaborazione qualsiasi (WM_MOUSEMOVE) Messaggio di pre-elaborazione/ciò che si desidera.

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

che rende solo il lavoro l'altro modo ... Voglio dire, ora che rileva quando il mouse si trova sopra il Modulo di controlli figlio, ma non il modulo stesso. Voglio rilevare l'intera cosa. Devo anche rilevare quando il mouse è entrato nel Form e quando è uscito, non solo che si sta muovendo all'interno. –

+0

Bene, ho trovato esattamente quello che stavo cercando in questo esempio: http://netcode.ru/dotnet/?lang=&katID=30&skatID=283&artID=7862. Utilizza lo stesso principio della tua risposta, IMessageFilter. E mi permette di rilevare quando il mouse entra e lascia il modulo. Devo solo adattare e spogliare il codice per quello che voglio. Ad ogni modo, se potessi elaborare la tua risposta su IMessageFilter, che cos'è, come funziona e tutto il resto, contrassegnerò questa risposta come accettata. E per favore aggiungi una nota per controllare i commenti per le altre persone che cercano una soluzione allo stesso identico problema. –

+0

Hai mai visto la mia richiesta Tcks? Forse lo fai questa volta ... Potresti per favore modificare il tuo post ed elaborare un po 'sull'intera cosa di IMessageFilter e come funziona? –

2

ne dite di questo: In OnLoad del modulo, in modo ricorsivo passare attraverso tutti i controlli figlio (ei loro figli) e collegare l'evento MouseEnter.

Quindi, ogni volta che il mouse immette qualsiasi discendente, verrà richiamato il gestore eventi. Allo stesso modo, è possibile collegare gli eventi MouseMove e/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

La chiamerei "soluzione" e non la soluzione, quindi no ... –

+0

Non funzionerà quando i controlli stanno cambiando durante la vita del modulo. – TcKs

0

Sul controllo utente creare un evento MouseHover per il controllo di questo tipo, (o altro tipo di evento) come questo

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

Sul WinFrom che ospita l'UserControl avere questo per l'UserControl per la gestione il MouseOver nel vostro Designer.cs

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

che chiama questo metodo sul tuo WinForm

private void ThumbnailMouseHover(object sender, EventArgs e) 
{ 

    ThumbImage thumb = (ThumbImage) sender; 

} 

Dove ThumbImage è il tipo di UserControl

0

Soluzione rapida e sporca:

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