Question

J'essaie de gérer un événement de souris sur une forme particulière qui devrait tirer si le curseur de la souris se situe entre un ensemble de coordonnées - disons un carré.

Je comprends que si j'avais une forme vide, je pouvais simplement lier à l'événement Mousemove et je pars. Mais en réalité, il peut y avoir jusqu'à 10 contrôles de chevauchement différents et dans mon application de test, l'événement Mousemove ne se déclenche que si le curseur est sur la forme réelle elle-même et non si c'est sur un contrôle de l'enfant.

Est-ce que quelqu'un sait comment gérer cet événement lorsqu'il y a un nombre inconnu de commandes d'enfants au moment de la conception?

Y a-t-il une seule ligne facile que je peux utiliser?

Était-ce utile?

La solution

À mon humble avis, il y a un peu une situation binaire ici: et il n'y a pas de «liner». La seule solution que je peux voir est d'obtenir vos contrôles qui n'implémentent pas d'événements dans un conteneur .NET qui le fait.

Lorsqu'un contrôle obtient un clic, le comportement attendu normal est qu'il deviendra le contrôle actif du formulaire (qui peut toujours être accessible par ce.ActivceControl).

Mais, en particulier si le contrôle que vous avez cliqué capture la souris, quelque chose doit augmenter un événement car .NET n'implémente pas l'événement "bouillonnant" (comme WPF le fait).

La façon habituelle de gérer le comportement étendant de tout objet scellé ou quoi que ce soit pour écrire une méthode d'extension, et j'ai trouvé des extensions d'écriture pour le contrôle assez facilement, mais je ne sais pas si cela vous aidera dans ce cas. Malheureusement, je suis hors de mon pays d'origine en ce moment et je n'ai pas Visual Studio avec qui jouer.

Une stratégie que vous pouvez utiliser pour déterminer si un point donné sur une forme se situe dans les limites de tout contrôle consiste à énumérer les zones (limites) de tous les contrôles sur le formulaire via «Forall of the Forms Control.Collection (This.Controls). Mais, si vous avez des contrôles qui se chevauchent, vous avez alors le problème de plus d'un contrôle contenant peut-être un point donné.

Meilleur, Bill

Autres conseils

essaye ça:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        AddMouseMoveHandler(this);
    }

    private void AddMouseMoveHandler(Control c)
    {
        c.MouseMove += MouseMoveHandler;
        if(c.Controls.Count>0)
        {
            foreach (Control ct in c.Controls)
                AddMouseMoveHandler(ct);
        }
    }

    private void MouseMoveHandler(object sender, MouseEventArgs e)
    {
        lblXY.Text = string.Format("X: {0}, Y:{1}", e.X, e.Y);
    }
}

Je sais que ce post est assez vieux, mais il me semble que la méthode la plus simple serait que le formulaire mette en œuvre IMessageFilter. Dans le constructeur (ou dans OnHandleCreated) tu appelles

Application.AddMessageFilter(this);

Et puis vous pouvez attraper les messages de toutes les fenêtres dans votre implémentation de IMessageFilter.PreFilterMessage.

Vous auriez probablement besoin d'utiliser P / Invoke pour la méthode Ischild Win32

[DllImport("user32.dll")]
public static extern bool IsChild(IntPtr hWndParent, IntPtr hWnd);

avec le formulaire Handle propriété pour vous assurer que vous gérez les bons messages.

Pourquoi n'utilisez-vous pas simplement les gestionnaires d'événements MouseOver des contrôles?

Je sais que je suis un peu en retard au punch, mais j'avais des problèmes avec ceci plus tôt dans la journée lors de l'utilisation d'un panneau comme barre de titre. J'avais une étiquette pour afficher du texte, une boîte d'images et quelques boutons tous imbriqués dans le panneau, mais j'avais besoin de piéger l'événement Mousemove malgré tout.

Ce que j'ai décidé de faire, c'est de mettre en œuvre un gestionnaire de méthodes récursives pour ce faire, car je n'avais qu'un seul niveau de contrôles imbriqués, cela peut ne pas être trop bien évolué lorsque vous commencez à aborder des niveaux de nidification ridicules.

Voici comment je l'ai fait:

    protected virtual void NestedControl_Mousemove(object sender, MouseEventArgs e)
    {
        Control current = sender as Control;
        //you will need to edit this to identify the true parent of your top-level control. As I was writing a custom UserControl, "this" was my title-bar's parent.
        if (current.Parent != this) 
        {
            // Reconstruct the args to get a correct X/Y value.
            // you can ignore this if you never need to get e.X/e.Y accurately.
            MouseEventArgs newArgs = new MouseEventArgs
            (
                e.Button, 
                e.Clicks, 
                e.X + current.Location.X, 
                e.Y + current.Location.Y, 
                e.Delta
            );
            NestedControl_Mousemove(current.Parent, newArgs);
        }
        else
        {
            // My "true" MouseMove handler, called at last.
            TitlebarMouseMove(current, e);
        }
    }

    //helper method to basically just ensure all the child controls subscribe to the NestedControl_MouseMove event.
    protected virtual void AddNestedMouseHandler(Control root, MouseEventHandler nestedHandler)
    {
        root.MouseMove += new MouseEventHandler(nestedHandler);
        if (root.Controls.Count > 0)
            foreach (Control c in root.Controls)
                AddNestedMouseHandler(c, nestedHandler);
    }

Et puis le configurer est relativement simple:

Définissez votre "vrai" gestionnaire:

    protected virtual void TitlebarMouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            this.Text = string.Format("({0}, {1})", e.X, e.Y);
        }
    }

Puis configurer les abonnés de l'événement des contrôles:

//pnlDisplay is my title bar panel.
AddNestedMouseHandler(pnlDisplay, NestedControl_Mousemove);

Relativement simple à utiliser, et je peux garantir le fait que cela fonctionne :)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top