Frage

Ich versuche, ein Mouseclick -Ereignis in einer bestimmten Form zu behandeln, die abfeuern sollte, wenn der Mauszeiger zwischen einer Reihe von Koordinaten fällt - sagen wir ein Quadrat.

Ich verstehe, wenn ich eine leere Form hätte, könnte ich einfach mit dem Mousemove -Event einbinden, und ich gehe. In Wirklichkeit gibt es jedoch bis zu 10 verschiedene überlappende Steuerelemente, und in meiner Test -App wird das MousEmove -Ereignis nur ausgelöst, wenn sich der Cursor auf der tatsächlichen Form selbst befindet und nicht, wenn es über eine Kinderkontrolle hinausgeht.

Weiß jemand, wie man mit diesem Ereignis umgeht, wenn es zur Entwurfszeit eine unbekannte Anzahl von Kindersteuerungen gibt?

Gibt es einen einfachen Einzeiler, den ich verwenden kann?

War es hilfreich?

Lösung

IMHO Es gibt hier eine gewisse binäre Situation: Und es gibt keinen "One-Liner". Die einzige Lösung, die ich sehen kann, besteht darin, Ihre Steuerelemente zu erhalten, die Ereignisse nicht in einen .NET -Container implementieren, der dies tut.

Wenn eine Steuerung ein Klick erhält, wird das normale erwartete Verhalten zur aktiven Kontrolle des Formulars (auf das immer zugegriffen werden kann. ActivCeControl).

Aber besonders, wenn die von Ihnen geklickte Steuerung die Maus erfasst, muss etwas ein Ereignis erhöhen, da .NET kein Ereignis "sprudeln" implementiert (wie WPF).

Der übliche Weg, um das Verhalten eines Versiegeltes oder was auch immer zu erweitern, ist das Schreiben einer Erweiterungsmethode, und ich habe festgestellt, dass das Schreiben von Erweiterungen für die Kontrolle ziemlich einfach ist, aber ich weiß nicht, ob dies Ihnen in diesem Fall hilft. Leider bin ich gerade nicht in meinem Heimatland und habe kein Visual Studio, mit dem ich herumspielen kann.

Eine Strategie, mit der Sie feststellen können, ob ein bestimmter Punkt in einem Formular innerhalb der Grenzen einer beliebigen Kontrolle fällt, besteht darin, die Bereiche (Grenzen) aller Kontrollpersonen über die Form der Formulare zu zählen. Wenn Sie jedoch überlappende Steuerelemente haben, haben Sie das Problem, dass mehr als eine Steuerung möglicherweise einen bestimmten Punkt enthält.

Am besten, Bill

Andere Tipps

Versuche dies:

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

Ich weiß IMessageFilter. Im Konstruktor (oder in OnHandleCreated) Du rufst an

Application.AddMessageFilter(this);

Und dann können Sie die Nachrichten aller Fenster in Ihrer Implementierung von fangen IMessageFilter.PreFilterMessage.

Sie müssten wahrscheinlich P/Invoke für die Win32 ISCHILD -Methode verwenden

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

zusammen mit der Form des Formulars Handle Eigenschaft, um sicherzustellen, dass Sie die richtigen Nachrichten abwickeln.

Warum verwenden Sie nicht einfach die Mauser -Event -Handler der Steuerung?

Ich weiß, dass ich etwas zu spät zum Schlag bin, aber ich hatte heute früher Probleme damit, als ich ein Panel als Titelleiste benutzte. Ich hatte ein Etikett, um einen Text, eine Bildbox und einige Schaltflächen anzuzeigen, die alle im Panel verschachtelt sind, aber ich musste das Mousemove -Ereignis trotzdem fangen.

Ich entschied mich dafür, einen rekursiven Methodenhandler zu implementieren, da ich nur 1 schorte Kontrollen hatte. Dies kann möglicherweise nicht zu gut skalieren, wenn Sie sich lächerlichen Nestern nähern.

So hat ich es gemacht:

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

Und dann ist es relativ einfach, es einzurichten:

Definieren Sie Ihren "wahren" Handler:

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

Und dann die Steuerungsereignisse abonniert:

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

Relativ einfach zu bedienen, und ich kann dafür bürgen, dass es funktioniert :)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top