كيفية التقاط أحداث Mousemove أسفل عناصر التحكم في الأطفال

StackOverflow https://stackoverflow.com/questions/1719636

سؤال

أحاول التعامل مع حدث MouseClick على شكل معين يجب إطلاق النار إذا كان مؤشر الماوس يقع بين مجموعة من الإحداثيات - دعنا نقول مربع.

أفهم أنه إذا كان لدي نموذج فارغ، فيمكنني ببساطة ربط حدث Mousemove وإيقاف تشغيله. ولكن في الواقع قد يكون هناك ما يصل إلى 10 عناصر تحكم متداخلة مختلفة وفي تطبيق اختبار MouseMove الحرائق فقط إذا كان المؤشر على شكله الفعلي نفسه وليس إذا كان على التحكم في الطفل.

هل يعرف أحد كيفية التعامل مع هذا الحدث عندما يكون هناك عدد غير معروف عن ضوابط الأطفال في وقت التصميم؟

هل هناك بطانة واحدة سهلة يمكنني استخدامها؟

هل كانت مفيدة؟

المحلول

IMHO هناك القليل من الوضع الثنائي هنا: ولا يوجد "بطانة واحدة". الحل الوحيد الذي يمكنني رؤيته هو الحصول على عناصر التحكم الخاصة بك التي لا تنفذ الأحداث في حاوية .NET تقوم بذلك.

عندما يحصل أي عنصر تحكم على نقرة، فإن السلوك الطبيعي المتوقع هو أنه سيصبح التحكم النشط للنموذج (والذي يمكن الوصول إليه دائما بهذا.

ولكن، إذا كان التحكم إذا قمت بالنقر فوق النقر فوق الماوس، فقد حصل شيء ما على رفع حدث منذ .NET لا ينفذ الحدث "Dubbles" (كما يفعل WPF).

الطريقة المعتادة للتعامل مع سلوك تمديد أي كائن مختوم أو أيا كان ما هو كتابة طريقة تمديد، ووجدت كتابة ملحقات للتحكم بسهولة، لكنني لا أعرف إذا كان ذلك سيساعدك في هذه الحالة. لسوء الحظ، أنا خارج البلد الخاص بي الآن، وليس لديك استوديو مرئي للعب حولها.

استراتيجية واحدة يمكنك استخدامها لتحديد ما إذا كانت نقطة معينة على شكل يقع داخل حدود أي عنصر تحكم هي تعداد المجالات (الحدود) من جميع عناصر التحكم في النموذج عبر "FORALL من Control Norks.Collection" (this.controls). ولكن، إذا كانت لديك عناصر تحكم متداخلة، فستكون لديك إذن أكثر من عنصر تحكم ربما يحتوي على نقطة معينة.

أفضل، فاتورة

نصائح أخرى

جرب هذا:

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

أعرف أن هذا المنشور قديم جدا، لكن يبدو لي أن أبسط طريقة ستكون للنموذج للتنفيذ IMessageFilter. وبعد في المنشئ (أو في OnHandleCreated) أنت أتصل

Application.AddMessageFilter(this);

ثم يمكنك التقاط رسائل جميع النوافذ في تنفيذك IMessageFilter.PreFilterMessage.

من المحتمل أن تحتاج إلى استخدام P / Invoke لطريقة Ischild Win32

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

جنبا إلى جنب مع النموذج Handle الممتلكات للتأكد من أنك تتعامل مع الرسائل المناسبة.

لماذا لا تستخدم فقط معدات الضوابط معالجات الأحداث Mouseover؟

أعلم أنني متأخرة بعض الشيء إلى لكمة، لكنني كنت أواجه مشاكل مع هذا في وقت سابق اليوم عند استخدام لوحة كشركة عنوان. كان لدي ملصق لعرض بعض النصوص، وصياغة وأزرار قليلة جميع المتداخلة داخل اللوحة، لكنني كنت بحاجة إلى فخ حدث Mousemove بغض النظر.

ما قررت القيام به كان ينفذ معالج طريقة متكررة للقيام بذلك، حيث كان لدي سوى مستوى واحد من عناصر التحكم المتداخلة، وقد لا يتجاوز ذلك بشكل جيد بشكل جيد عندما تبدأ تقترب من مستويات سخيفة من التعشيش.

إليك كيف فعلت ذلك:

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

ثم لإعداده بسيط نسبيا:

تحديد المعالج "الحقيقي" الخاص بك:

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

ثم قم بإعداد مشتركي أحداث الضوابط:

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

بسيطة نسبيا للاستخدام، ويمكنني أن أشهد حقيقة أنها تعمل :)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top