bubarnet
bubarnet

Reputation: 101

Drag'n Drop : tell the sender when drop occurs

I'm using c# 3.5 / winforms

On my form, I have 2 picturebox PB1 and PB2 (and lots of others controls), in a panel. The user can drag PB1 to PB2. But he can also cancel the drop by release the left button anywhere on the form or outside the form. PB1 can be dragged a fixed number of times. When the drag start, I decrease a variable in PB1 and if it reach 0, the PB became invisible.

But if the user cancel the drag, PB1 must know that to increase the variable and set the visibility of PB1.

My problem is : how PB1 can know when a drag is canceled (or actually, dropped, even on a valid control) ? Remember that the user can release the drag outside of the form, so I can't use the Drop event on the form. I try the GiveFeedback and the QueryContinueDrag events, but they are fired as long as the drag continue, but not when it stop.

Some code :

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

Upvotes: 0

Views: 655

Answers (1)

Idle_Mind
Idle_Mind

Reputation: 39152

"there are 1 to 4 valid targets."

In this example we are dragging pictureBox1, and pictureBox2 thru pictureBox5 are the valid drop targets. We create a DataObject with a custom name to encapsulate pictureBox1 during the drag/drop operation. In the drop targets, we only allow a drop if the custom name is present in the thing being dragged. This ensures we only get a DragDrop event from pictureBox1 itself, and we know it's safe to decrement our drop counter. We can retrieve pictureBox1 back from the DataObject and change its state so that it can no longer be dropped:

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

}

Upvotes: 2

Related Questions