2011-02-14 4 views
7

Il y a certainement un moyen pratique de le faire:
Winforms: Intercepter événement de souris sur le formulaire principal en premier, et non sur les contrôles

J'ai mis en place un « Déplacer la fenêtre » sur le comportement de glisser la souris sur ma forme principale,
et Je voudrais que l'événement MouseClick/Move soit intercepté par le formulaire, pas par les contrôles qui s'y trouvent.

Je voudrais trouver un équivalent/reproduire la propriété « KeyPreview » pour les événements de souris

De plus, je veux éviter Réorienter l'événement souris au formulaire principal Méthode 12 fois dans les événements de souris de 12 Commandes individuellement (qui est la solution de contournement laid que j'ai trouvé jusqu'à présent)

Des idées?

+0

Est-ce que les contrôles enfants gèrent également les événements click/move de la souris? – tzup

+0

Certains d'entre eux, pas tous. Et je veux certainement éviter de rediriger l'événement de souris à la méthode de formulaire principal 12 fois dans 12 contrôles –

+1

Vous pouvez utiliser un [filtre de message] (http://stackoverflow.com/questions/4279732/). (Réponse triviale convertie pour commenter automatiquement.) – ulatekh

Répondre

1

Sur la base de vos commentaires,

Mettre en oeuvre la fonctionnalité de redirection de l'événement de la souris dans une classe de base, puis faire tous les contrôles dérivent de cette classe de base.

Ainsi, vous n'implémentez la fonctionnalité qu'une seule fois et ensuite tous vos contrôles vont «relancer» l'événement de souris pour être capturé par le formulaire principal.

Espérons que cela aide.

+0

Oui, j'ai pensé à ça ... Mais cela me fait changer le code hérité plus que ce que je suis prêt à faire. Je me demandais si il n'y avait pas un moyen de contourner complètement les contrôles ... –

4

Abonnez-vous à tous les contrôles événements MouseMove (considérez-récursivement pour les contrôles imbriqués)

foreach (Control control in Controls) 
    control.MouseMove += RedirectMouseMove; 

et augmenter MouseMove dans ce gestionnaire d'événements

private void RedirectMouseMove(object sender, MouseEventArgs e) 
{ 
    Control control = (Control)sender; 
    Point screenPoint = control.PointToScreen(new Point(e.X, e.Y)); 
    Point formPoint = PointToClient(screenPoint); 
    MouseEventArgs args = new MouseEventArgs(e.Button, e.Clicks, 
     formPoint.X, formPoint.Y, e.Delta); 
    OnMouseMove(args); 
} 

Gardez à l'esprit que les contrôles reçoivent MouseEvents avec les coordonnées locales de contrôle. Vous devez donc le convertir pour former des coordonnées. Il y a peut être des inconvénients avec des contrôles imbriqués, mais je vous laisse (par exemple appeler Parent.PointToClient)

MISE À JOUR: Vous êtes seront toujours en mesure de gérer les événements de contrôle - il suffit de vous inscrire à l'événement une fois de plus .

+0

Comme indiqué dans un autre commentaire, je me demandais s'il n'y avait pas un moyen de contourner complètement les contrôles ... –

+0

Mais KeyPreview fonctionne presque de la même manière (attendue propriété de argument d'événement) - il contourne les contrôles et gère l'événement en premier au niveau du formulaire. –

2

Vous pouvez utiliser un crochet global de la souris pour intercepter les événements de la souris, il y a un sample on MSDN

1

Remplacer la Control.PreProcessMessage Méthode:

http://msdn.microsoft.com/en-us/library/system.windows.forms.control.preprocessmessage.aspx

Edit:

Il semble PreProcessMessage pourrait ne pas fonctionner pour les événements de souris. Essayez de remplacer WndPrc à la place. Il peut intercepter les messages de la souris pour vous, mais vous devez voir si elle les intercepte dans l'ordre que vous voulez:

http://bytes.com/topic/c-sharp/answers/752144-preprocessmessage

+0

Où est-ce que je fais ça? Sur le formulaire principal? Cela contournerait les contrôles? –

+0

Si j'ai bien compris votre question - oui! – Pedery

0

Vous pouvez utiliser GlobalMouseKeyHook library facilement système d'interception large de la souris de position.

Au clic de la souris, vous devriez alors vérifier si l'emplacement de la souris croise votre formulaire OU si les fenêtres sous votre souris sont votre formulaire.

Pour faire cette dernière chose dont vous avez besoin fonction API WindowFromPoint:

[DllImport("user32.dll", SetLastError = true)] 
    public static extern IntPtr WindowFromPoint([In] POINTAPI Point); 

    private void _mouseListener_MouseClick(object sender, MouseEventArgs e) 
    { 
     var localPoint = this.PointToClient(e.Location); 
     bool containsPoint = this.ClientRectangle.Contains(localPoint); 

     var windowHandle = WindowFromPoint(e.Location); 
     var ctl = (Form)Form.FromHandle(windowHandle); 
     bool mainFormClicked = ctl != null && ctl.Handle == this.Handle; 

     if(containsPoint && mainFormClicked ) 
     { 
       //form click is intercepted! 
     } 
    } 

En fait, j'utiliser quand je veux intercepter cliquez en dehors de ma forme (il n'y a pas d'autre moyen). Dans votre cas, je me lierais à MouseClick de chaque contrôle pour des raisons de performances (le hook global est lourd).

Questions connexes