Drag'n Drop:在发生丢弃时告诉发件人

时间:2017-01-19 19:50:29

标签: c# winforms drag-and-drop

我正在使用c#3.5 / winforms

在我的表格中,我在面板中有2个图片框PB1和PB2(以及许多其他控件)。 用户可以将PB1拖到PB2。但他也可以通过在表单上或表单外的任何位置释放左键来取消删除。 PB1可以拖动固定次数。当拖动开始时,我减少PB1中的变量,如果它达到0,则PB变得不可见。

但是如果用户取消拖动,PB1必须知道增加变量并设置PB1的可见性。

我的问题是:PB1如何知道拖动被取消(或实际上,甚至在有效控件上被删除)?请记住,用户可以释放窗体外的拖动,因此我无法在窗体上使用Drop事件。我尝试GiveFeedback和QueryContinueDrag事件,但只要拖动继续,它们就会被触发,但是当它停止时它们就会被触发。

一些代码:

class COPGOJetonImage
{
    private PictureBox PB1;

    public COPGOJetonImage()
    {
        PB1 = new PictureBox();
        //here I initialize PB1
        ((Control)PB1).AllowDrop = true; //in case of
        PB1.MouseDown += OnMouseDown;
    }
    public void OnMouseDown(object sender, MouseEventArgs ev)
    {
        PB1.DoDragDrop(PB1.Image, DragDropEffects.Copy);
    }
}

1 个答案:

答案 0 :(得分:2)

" 有1到4个有效目标。"

在此示例中,我们拖动pictureBox1,而pictureBox2pictureBox5是有效的放置目标。我们使用自定义名称创建一个DataObject,以便在拖放操作期间封装pictureBox1。在放置目标中,如果被拖动的东西中存在自定义名称,我们只允许放弃。这确保我们只从pictureBox1本身获得DragDrop事件,并且我们知道减少我们的丢弃计数器是安全的。我们可以从DataObject中检索pictureBox1并更改其状态,以便不再删除它:

public partial class Form1 : Form
{

    public Form1()
    {
        InitializeComponent();
    }

    private int DropsLeft = 5;
    private string DataFormatName = "YourUniqueDataFormatNameHere";

    private void Form1_Load(object sender, EventArgs e)
    {
        pictureBox1.MouseMove += PictureBox1_MouseMove;

        PictureBox[] pbs = new PictureBox[] { pictureBox2, pictureBox3, pictureBox4, pictureBox5 };
        foreach (PictureBox pb in pbs)
        {
            pb.AllowDrop = true;
            pb.DragEnter += Pb_DragEnter;
            pb.DragDrop += Pb_DragDrop;
        }
    }

    private void PictureBox1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            DataObject data = new DataObject(DataFormatName, pictureBox1);
            pictureBox1.DoDragDrop(data, DragDropEffects.Copy);
        }
    }

    private void Pb_DragEnter(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent(DataFormatName))
        {
            e.Effect = DragDropEffects.All;
        }
        else
        {
            e.Effect = DragDropEffects.None;
        }
    }

    private void Pb_DragDrop(object sender, DragEventArgs e)
    {
        DropsLeft--;

        // retrieve the data
        PictureBox pb = (PictureBox)e.Data.GetData(DataFormatName);

        if (DropsLeft == 0)
        {
            MessageBox.Show("No more drops left!");
            pb.Enabled = false;
            pb.BackColor = Color.Red; // for visual effect
        }
    }

}