2009-06-12 22 views
7

J'ai besoin de détecter quand l'utilisateur déplace la souris sur le formulaire et tous ses contrôles enfants et aussi quand il quitte le formulaire. J'ai essayé les MouseEnter et MouseLeave événements du formulaire, j'ai essayé le WM_MOUSEMOVE & WM_MOUSELEAVE et WM_NCMOUSEMOVE & WM_NCMOUSELEAVE paires de messages Windows, mais aucun ne semble fonctionner comme je veux ...Comment détecter si la souris est à l'intérieur de la forme entière et des contrôles enfants?

La plupart de ma forme est occupée par les contrôles enfants de De nombreuses sortes, il n'y a pas beaucoup de zone client visible. Cela signifie que si je bouge la souris très rapidement, le mouvement de la souris ne sera pas détecté, bien que la souris soit à l'intérieur du formulaire. Par exemple, j'ai un TextBox qui est ancré en bas et entre le bureau et le TextBox, il n'y a qu'une très petite bordure. Si je déplace rapidement la souris du bas vers la TextBox, le mouvement de la souris ne sera pas détecté, mais la souris se trouve dans le TextBox, donc dans le formulaire.

Comment puis-je obtenir ce dont j'ai besoin?

Répondre

13

Vous pouvez raccorder la boucle de message principale et pré-traiter/post-traiter n'importe quel message (WM_MOUSEMOVE) comme vous le souhaitez.

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

Cela ne fait que ça marche dans l'autre sens ... Je veux dire, il détecte maintenant quand la souris est sur le formulaire de contrôles enfants, mais pas le formulaire lui-même. Je veux détecter la chose ENTIER. J'ai également besoin de détecter quand la souris est entrée dans le formulaire et quand elle est partie, pas seulement qu'elle bouge à l'intérieur. –

+0

Eh bien, j'ai trouvé exactement ce que je cherchais dans cet exemple: http://netcode.ru/dotnet/?lang=&katID=30&skatID=283&artID=7862. Il utilise le même principe que votre réponse, le IMessageFilter. Et cela me permet de détecter quand la souris entre et quitte le formulaire. Je dois juste adapter et dépouiller le code à ce que je veux. Quoi qu'il en soit, si vous pouviez développer votre réponse sur IMessageFilter, ce que c'est, comment ça marche et tout ça, je marquerai cette réponse comme la réponse acceptée. Et s'il vous plaît ajouter une note pour vérifier les commentaires pour les autres personnes à la recherche d'une solution au même problème. –

+0

Avez-vous même vu ma demande TcKS? Peut-être que vous faites cette fois ... Pourriez-vous s'il vous plaît modifier votre poste et élaborer un peu sur l'ensemble IMessageFilter chose et comment cela fonctionne? –

2

Que diriez-vous ceci: En OnLoad de votre forme, allez récursive à travers tous les contrôles enfants (et leurs enfants) et accrochez l'événement MouseEnter.

Ensuite, chaque fois que la souris entre dans un descendant, le gestionnaire d'événements sera appelé. De même, vous pouvez connecter des événements MouseMove et/ou 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

J'appellerais cela une "solution de contournement" et non la solution, donc non ... –

+0

Cela ne fonctionnera pas lorsque les contrôles changent pendant la vie du formulaire. – TcKs

0

Sur votre contrôle utilisateur Créer un événement MouseHover pour votre contrôle comme celui-ci, (ou tout autre type d'événement) comme celui-ci

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

Sur votre WinFrom qui accueille UserControl cette pour le UserControl à manipuler le MouseOver dans votre Designer.cs

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

qui appelle cette méthode sur votre WinForm

private void ThumbnailMouseHover(object sender, EventArgs e) 
{ 

    ThumbImage thumb = (ThumbImage) sender; 

} 

Où ThumbImage est le type de usercontrol

0

Solution rapide et sale:

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