MattyG
MattyG

Reputation: 8497

Prevent drag and drop outside of the current control (TreeNodes in a TreeView)

I'm maintaining a Windows app that has multiple forms in the one window (form1, form2, form3). I'm treating the other form2 and form3 as black boxes at the moment. In form1 I have a TreeView, and I'm implementing drag and drop functionality within that TreeView.
How can I prevent a drop outside of the form1 control?

I'm implementing 3 events handlers:

private void treeView_ItemDrag (...)
{
    DoDragDrop(e.Item, DragDropEffects.Move);
} 

private void treeView_DragEvent (...) 
{
    e.Effect = DragDropEffects.Move;
}

private void treeView_DragDrop (...)
{
    //the node move logic here
}

form2 and form3 have a drag and drop relationship between them, so when I drag a node from form1 into form3 by default it allows the move (bad). I want to be able to prevent this from the form1 control code.

How can I prevent a drop outside of the form1 control? I've looked at the _DragLeave event, but I'm unsure how to control the operation without the DragEventArgs.

Upvotes: 4

Views: 2812

Answers (3)

Frank Ball
Frank Ball

Reputation: 1126

I know this is an old topic, but since I've never found a good answer to how to prevent dragging a control outside of a panel, I thought that I'd throw in the solution that I put together. I used some the tips from above and some work of my own.

private void Form1_Load(object sender, EventArgs e)
        {
            _originalClip = Cursor.Clip;
        }

        private void pb_MouseMove(object sender, MouseEventArgs e)
        {
            PictureBox pb = (PictureBox)sender;
            if (e.Button == MouseButtons.Left)
            {
                Size sz = new Size(panel1.RectangleToScreen(panel1.ClientRectangle).Width - (pb.Width), panel1.RectangleToScreen(panel1.ClientRectangle).Height - (pb.Height));
                Point loc = new Point(panel1.RectangleToScreen(panel1.ClientRectangle).X + (pb.Width / 2), panel1.RectangleToScreen(panel1.ClientRectangle).Y + (pb.Height / 2));
                Rectangle rct = new Rectangle(loc, sz);
                Cursor.Clip = rct;
                pb.Left += (e.X - x);
                pb.Top += (e.Y - y);
            }
        }
        private void pb_MouseUp(object sender, MouseEventArgs e)
        {
            Cursor.Clip = _originalClip;
        }

What this does is uses the Cursor.Clip method along with a Rectangle object with it's size set to be the size of the panel ("panel1" in the code) containing a bunch of Pictureboxes ("pb" in the code). The new rectangle's size is set to the parent panel minus the width and height of the Picturebox and it's location set to the location of panel1 minus half of the Picturebox's width and height. This gives you a rectangle which will constrain the Picturebox from being drug outside the panel.

Upvotes: 1

jjokela
jjokela

Reputation: 337

You can check if mouse drag action is going outside the allowed area, and if so, cancel the drag action.

There's a nice sample in MSDN that uses the QueryContinueDrag event for that purpose. I think you can use that on the base of your solution.

Link: DragAction Enumeration

Upvotes: 2

Steve
Steve

Reputation: 216353

There is this little know property in the Cursor object that can restrict the mouse movement only to a certain rectangle.

this as a global variable for Form1

   Rectangle _originalClip;

this goes in your Form1_Load event

  _originalClip = Cursor.Clip;

this could be in your treeView.ItemDrag, forcing the cursor inside the form1 client area

   Cursor.Clip = form1.RectangleToScreen(form1.ClientRectangle);

Now you need to restore the original clip area. A good place will be in the treeView.DragDrop. But to be on the safe side put also in your Form1_Closing event

   Cursor.Clip = _originalClip;

Upvotes: 6

Related Questions