19 Jul 2008

C#: Drag and Drop – Part 2

1 Comment Programming

Last week I posted about drag and drop in C#. The post covered pre-built controls (TreeView and ListView). There are a few things the post didn't cover, such as user controls and anything which doesn't raise the ItemDrag event.

To be able to drag a user control, the control has to call the DoDragDrop method. The logical way to do this is by tracking the state of the left mouse button. If the left button is pressed and the mouse moves, start the drag/drop.

private bool isDragging = false;
...
private void userControl_MouseDown(object sender, MouseEventArgs e) {
    this.isDragging = true;
};
private void userControl_MouseUp(object sender, MouseEventArgs e) {
    this.isDragging = false;
};
private void userControl_MouseLeave(object sender, EventArgs e) {
    isDragging = false;
};
private void userControl_MouseMove(object sender, MouseEventArgs e) {
    if(isDragging) {
        DoDragDrop(userControl, DragDropEffects.Move);
    }
};

There are three delegates assigned to listen to events. When the mouse is pressed a flag is set, when it's released, the flag is unset. If the mouse moves while the mouse is pressed, a drag and drop operation is started. The flag is also unset when the mouse moves out of the control's bounds. This stops the operation from being restarted when the mouse re-enters the control after dropping elsewhere. Once you have the data, the rest of the drop is the same.

Another thing which is useful is changing the operation based on the state of the Ctrl and Shift keys. Depending on the application, different combinations of shift and ctrl are used to copy, move or link when dragging.

To obtain the state of the keys, you'll need to use P/Invoke. Thanks pinvoke.net for the method signatures.

[DllImport("user32.dll")]
protected static extern short GetAsyncKeyState(int vKey);
 
private void userControl_MouseMove(object sender, MouseEventArgs e) {
    if(isDragging) {
        if(GetAsyncKeyState((int)Keys.ShiftKey) < 0 || GetAsyncKeyState((int)Keys.ControlKey) < 0) {
            DoDragDrop(this, DragDropEffects.Copy);
        } else {
            DoDragDrop(this, DragDropEffects.Move);
        }
    }
};

Then you'll also need to check the state in the DragEnter listener in the control where the data can be dropped.

Tags: , , , , , ,
written by
The author didn‘t add any Information to his profile yet.

One Response to “C#: Drag and Drop – Part 2”

  1. Reply Piyoosh says:

    I believe the code shown above would fire DoDragDrop multiple times during the drag operation. So, we may need to set isDragging to false in userControl_MouseMove after firing DoDragDrop.

Leave a Reply