سؤال

هل هناك طريقة سهلة للتأكد من أنه بعد فشل عملية السحب والإفلات، لن يتم تناول حدث MouseUp وتجاهله بواسطة إطار العمل؟

لقد وجدت منشور مدونة يصف آلية واحدة, ، ولكنه يتضمن قدرًا كبيرًا من مسك الدفاتر اليدوي، بما في ذلك علامات الحالة، وأحداث MouseMove، والتحقق اليدوي من "ترك الماوس"، وما إلى ذلك.وكل ذلك لا أود أن أضطر إلى تنفيذه إذا كان من الممكن تجنبه.

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

المحلول

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

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

إليك الكود الذي سأشرحه أدناه:

this.LabelDrag.QueryContinueDrag += new System.Windows.Forms.QueryContinueDragEventHandler(this.LabelDrag_QueryContinueDrag);
this.LabelDrag.MouseDown += new System.Windows.Forms.MouseEventHandler(this.LabelDrag_MouseDown);
this.LabelDrag.MouseUp += new System.Windows.Forms.MouseEventHandler(this.LabelDrag_MouseUp);

this.LabelDrop.DragDrop += new System.Windows.Forms.DragEventHandler(this.LabelDrop_DragDrop);
this.LabelDrop.DragEnter += new System.Windows.Forms.DragEventHandler(this.LabelMain_DragEnter);

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

    private void LabelDrop_DragDrop(object sender, DragEventArgs e)
    {
        LabelDrop.Text = e.Data.GetData(DataFormats.Text).ToString();
    }


    private void LabelMain_DragEnter(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent(DataFormats.Text))
            e.Effect = DragDropEffects.Copy;
        else
            e.Effect = DragDropEffects.None;

    }

    private void LabelDrag_MouseDown(object sender, MouseEventArgs e)
    {
        //EXTREMELY IMPORTANT - MUST CALL LabelDrag's DoDragDrop method!!
        //Calling the Form's DoDragDrop WILL NOT allow QueryContinueDrag to fire!
        ((Label)sender).DoDragDrop(TextMain.Text, DragDropEffects.Copy); 
    }

    private void LabelDrag_MouseUp(object sender, MouseEventArgs e)
    {
        LabelDrop.Text = "LabelDrag_MouseUp";
    }

    private void LabelDrag_QueryContinueDrag(object sender, QueryContinueDragEventArgs e)
    {
        //Get rect of LabelDrop
        Rectangle rect = new Rectangle(LabelDrop.Location, new Size(LabelDrop.Width, LabelDrop.Height));

        //If the left mouse button is up and the mouse is not currently over LabelDrop
        if (Control.MouseButtons != MouseButtons.Left && !rect.Contains(PointToClient(Control.MousePosition)))
        {
            //Cancel the DragDrop Action
            e.Action = DragAction.Cancel;
            //Manually fire the MouseUp event
            LabelDrag_MouseUp(sender, new MouseEventArgs(Control.MouseButtons, 0, Control.MousePosition.X, Control.MousePosition.Y, 0));
        }
    }

}

لقد أهملت معظم أكواد المصمم، لكنني قمت بتضمين كود رابط معالج الأحداث حتى تتمكن من التأكد مما يرتبط بماذا.في المثال الخاص بي، يحدث السحب/الإفلات بين التسميات LabelDrag وLabelDrop.

الجزء الرئيسي من الحل الخاص بي هو استخدام حدث QueryContinueDrag.يتم تشغيل هذا الحدث عندما تتغير حالة لوحة المفاتيح أو الماوس بعد استدعاء DoDragDrop على عنصر التحكم هذا.من المحتمل أنك تقوم بذلك بالفعل، ولكن من المهم جدًا أن تقوم باستدعاء الأسلوب DoDragDrop لعنصر التحكم الذي يمثل مصدرك وليس الأسلوب المرتبط بالنموذج.وإلا فلن يتم إطلاق QueryContinueDrag!

شيء واحد يجب ملاحظته هو أن QueryContinueDrag سيتم إطلاقه فعليًا عند تحرير الماوس على التحكم في الهبوط لذلك نحن بحاجة للتأكد من أننا نسمح بذلك.تتم معالجة ذلك عن طريق التحقق من أن موضع الماوس (الذي تم استرداده باستخدام خاصية Control.MousePosition العالمية) موجود داخل مستطيل التحكم LabelDrop.يجب عليك أيضًا التأكد من تحويل MousePosition إلى نقطة تتعلق بنافذة العميل باستخدام PointToClient حيث يقوم Control.MousePosition بإرجاع قيمة الشاشة النسبية موضع.

وذلك عن طريق التحقق من أن الماوس لا عبر عنصر التحكم بالإسقاط وأن زر الماوس موجود الآن أعلى لقد نجحنا في التقاط حدث MouseUp للتحكم في LabelDrag!:) الآن، يمكنك إجراء أي عملية معالجة تريد إجراؤها هنا، ولكن إذا كان لديك بالفعل رمز تستخدمه في معالج الأحداث MouseUp، فهذا غير فعال.لذا، ما عليك سوى استدعاء حدث MouseUp الخاص بك من هنا، وتمرير المعلمات الضرورية إليه ولن يعرف معالج MouseUp الفرق أبدًا.

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

امل ان يساعد!

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