Performing Drag-and-Drop Operations

 

Mike Gunderloy
Lark Group, Inc.

February 2002

Summary: Managing drag-and-drop in Microsoft Visual Basic .NET. (9 printed pages)

Objectives

  • Understand drag-and-drop in Windows Forms
  • Use Microsoft Visual Basic® .NET code to perform drag-and-drop operations

Assumptions

The following should be true for you to get the most out of this document:

  • You are familiar with Visual Basic programming
  • You understand the basic concept of drag-and-drop
  • You have access to Visual Basic .NET

Contents

Drag-and-Drop
Practice Implementing Drag-and-Drop
Summary

Drag-and-Drop

Drag-and-drop is one of the fundamental metaphors underlying the Microsoft® Windows® family of operating systems. Users understand that some items can be moved around by holding the mouse down on them, and that they'll get appropriate visual feedback when they're over a spot where the item can be dropped. They expect to be able to move data and images from one spot to another this way. Visual Basic .NET makes it easy to implement drag-and-drop in your own applications. You can control all aspects of the process, including which controls allow dragging, what data they make available to drag, and where it can be dropped. You can implement this both within a single application and between applications. In this document, you'll learn how to manage drag-and-drop in Visual Basic .NET.

Note If you worked with OLE drag-and-drop in Visual Basic 6.0, you'll find that drag-and-drop in Microsoft .NET is very similar. But a number of terms and names have changed, so read the details carefully.

Beginning a Drag-and-Drop Operation

To begin a drag-and-drop operation, you call the DoDragDrop method of a Windows Forms control. The DoDragDrop method is implemented on the System.Windows.Forms.Control class, which means that it is available on all controls within the Windows Forms namespace.

The DoDragDrop method takes two arguments: the data to be dragged, and the drag operations that this control allows. You can call the DoDragDrop method at any time, although most frequently you'll want to use the MouseDown event as a way to trigger dragging when the user expects it. For example:

Private Sub txtDrag_MouseDown(ByVal sender As Object, _
 ByVal e As System.Windows.Forms.MouseEventArgs)_
 Handles txtDrag.MouseDown

    txtDrag.DoDragDrop(txtDrag.Text, _
     DragDropEffects.Copy Or DragDropEffects.Move)

End Sub

In this particular case, the code starts a drag operation whenever the user depresses the primary mouse button on the txt1 control. The data to be dragged is the text contained in the control, and the control allows both copy and move operations in drag-and-drop.

**Tip   **The data to be dragged should be an instance of the String, Bitmap, or MetaFile class, or an object that implements the ISerializable or IDataObject interfaces.

The second argument to the DoDragDrop method is a combination of members from the DragDropEffects enumeration, indicating which target operations are valid for this data. Table 1 shows the members of this enumeration.

Table 1. DragDropEffects enumeration members

Member Explanation
All The data is copied, removed from the drag source, and scrolled in the target.
Copy The data is copied to the target.
Link The data is linked to the target.
Move The data is moved to the target.
None The target does not accept the data.
Scroll Scrolling is about to start or currently occurring in the target.

Accepting Data From a Drag Operation

Any control can accept data from a drag-and-drop operation in progress. To designate a control as a drop zone, you must do three things:

  1. Set the AllowDrop property of the control to True.
  2. Handle the DragEnter property of the control.
  3. Handle the DragDrop property of the control.

The DragEnter event occurs when a drag-and-drop operation is in progress (that is, some control has called the DoDragDrop method) and the cursor enters the control. This event passes an argument of the System.Windows.Forms.DragEventArgs class. You should set the Effect property of this argument to a value from Table 1 to indicate the action that will be taken if the operation is completed on this control. The system will use this value to pick the appropriate drop cursor to display. For example:

Private Sub txtDrop_DragEnter(ByVal sender As Object, _
 ByVal e As System.Windows.Forms.DragEventArgs) _
 Handles txtDrop.DragEnter

    If (e.Data.GetDataPresent(DataFormats.Text)) Then
        If (e.KeyState And CtrlMask) = CtrlMask Then
            e.Effect = DragDropEffects.Copy
        Else
            e.Effect = DragDropEffects.Move
        End If
    End If

End Sub

In this particular case, the code examines the KeyState property of the DragEventArgs argument to determine whether the Ctrl key is depressed as part of the drag operation. If it is, the control accepts this potential drop as a copy; if not, it accepts the drop as a move.

The DragEnter event provides visual feedback to the user that a drop is allowed on this particular control. If the user actually releases the mouse button on this control, then the DragDrop event is triggered. In this event, you should handle the actual mechanics of processing the dropped data. For example, this procedure inserts the dropped data into the target control:

Private Sub txtDrop_DragDrop(ByVal sender As Object, _
 ByVal e As System.Windows.Forms.DragEventArgs) _
 Handles txtDrop.DragDrop
    txtDrop.Text = e.Data.GetData(DataFormats.Text)
End Sub

Other Drag-and-Drop Events

There are two other events the can be triggered on a target control as part of a drag-and-drop operation: DragOver and DragLeave.

The DragOver event happens as the cursor continues to move within the same control (similar to the MouseMove event):

Private Sub txtDrop_DragOver(ByVal sender As Object, _
 ByVal e As System.Windows.Forms.DragEventArgs) _
 Handles txtDrop.DragOver
    …
End Sub

The DragLeave event happens when the cursor moves out of a control that was a potential drop target:

Private Sub txtDrop_DragLeave(ByVal sender As Object, _
 ByVal e As System.EventArgs) _
 Handles txtDrop.DragLeave
    …
End Sub

Note that in the DragLeave event you do not have access to the DragEventArgs object. This event is useful for "cleaning up" any changes you made to the drop target when a drop doesn't happen. For example, you might highlight a target control during the DragEnter event and remove the highlight during the DragLeave event.

Drag-and-Drop Between Applications

You don't have to take any special steps to allow drag-and-drop between applications. Once you've started a drag-and-drop operation with the DoDragDrop method, the user can drag the data to any drop target within your application or in any other application. Only two conditions must be satisfied for an inter-application drag-and-drop operation to succeed:

  1. The drop target must allow at least one of the drag effects that were specified during the DoDragDrop method call.
  2. The drop target must accept the data in the format that the drag control provided.

Practice Implementing Drag-and-Drop

In the following example, you will implement drag-and-drop between controls in a simple Windows Forms component. You'll drag data within the application, and then drag the data from your application to another Windows application.

To create a drag-and-drop test project

  1. Open Visual Studio .NET and choose New Project from the Start Page.

  2. Select Visual Basic Project from the tree view on the left side of the screen.

  3. Select Windows Application as the project template.

  4. Set the name of the application to DragDrop and click OK to create the project.

  5. Highlight the form called Form1.vb in the Solution Explorer window and rename it to frmDragDrop.vb.

  6. Create the form shown in Figure 1 by adding the appropriate controls and setting the properties of those controls, as outlined in Table 2.

    Table 2: Controls for frmDragDrop.vb

    Control Type Property Value
    TextBox Name txt1
      Text (blank)
    TextBox Name txt2
      Text (blank)
    TextBox Name txt3
      Text (blank)
    TextBox Name txt4
      Text (blank)
    ListBox Name lboTarget
      AllowDrop True

    Figure 1. The drag-and-drop test form

Add Code to Implement Drag-and-Drop

Now you're ready to write code to perform drag-and-drop operations within this form. You'll write code to generate random values in the four text boxes, and then implement drag-and-drop from the text boxes to the list box. The list box code will complete the drag as a copy if the Ctrl key is pressed while the value is being dragged, otherwise it will create the drag as a move.

On the View menu, click Code and enter this code before the Windows Form Designer-generated code:

Const CtrlMask = 8
Private SourceControl As TextBox

Now enter this code after the Windows Form Designer-generated code:

Private Sub Form1_Load(ByVal sender As System.Object, _
 ByVal e As System.EventArgs) Handles MyBase.Load
    Randomize()
    txt1.Text = Int(Rnd(1) * 10) + 1
    txt2.Text = Int(Rnd(1) * 10) + 1
    txt3.Text = Int(Rnd(1) * 10) + 1
    txt4.Text = Int(Rnd(1) * 10) + 1
End Sub

Private Sub txt1_MouseDown(ByVal sender As Object, _
 ByVal e As System.Windows.Forms.MouseEventArgs) _
 Handles txt1.MouseDown
    If Len(txt1.Text) > 0 Then
        SourceControl = txt1
        txt1.DoDragDrop(txt1.Text, _
         DragDropEffects.Copy Or DragDropEffects.Move)
    End If
End Sub

Private Sub txt2_MouseDown(ByVal sender As Object, _
 ByVal e As System.Windows.Forms.MouseEventArgs) _
 Handles txt2.MouseDown
    If Len(txt2.Text) > 0 Then
        SourceControl = txt2
        txt2.DoDragDrop(txt2.Text, _
         DragDropEffects.Copy Or DragDropEffects.Move)
    End If
End Sub

Private Sub txt3_MouseDown(ByVal sender As Object, _
 ByVal e As System.Windows.Forms.MouseEventArgs) _
 Handles txt3.MouseDown
    If Len(txt3.Text) > 0 Then
        SourceControl = txt3
        txt3.DoDragDrop(txt3.Text, _
         DragDropEffects.Copy Or DragDropEffects.Move)
    End If
End Sub

Private Sub txt4_MouseDown(ByVal sender As Object, _
 ByVal e As System.Windows.Forms.MouseEventArgs) _
 Handles txt4.MouseDown
    If Len(txt4.Text) > 0 Then
        SourceControl = txt4
        txt4.DoDragDrop(txt4.Text, _
         DragDropEffects.Copy Or DragDropEffects.Move)
    End If
End Sub

Private Sub lboTarget_DragEnter( _
 ByVal sender As System.Object, _
 ByVal e As System.Windows.Forms.DragEventArgs) _
 Handles lboTarget.DragEnter
    If (e.Data.GetDataPresent(DataFormats.Text)) Then
        If (e.KeyState And CtrlMask) = CtrlMask Then
            e.Effect = DragDropEffects.Copy
        Else
            e.Effect = DragDropEffects.Move
        End If
    End If
End Sub

Private Sub lboTarget_DragDrop( _
 ByVal sender As System.Object, _
 ByVal e As System.Windows.Forms.DragEventArgs) _
 Handles lboTarget.DragDrop
    lboTarget.Items.Add(e.Data.GetData(DataFormats.Text))
    If (e.KeyState And CtrlMask) <> CtrlMask Then
        SourceControl.Clear()
    End If
    SourceControl = Nothing
End Sub

Here's what you'll find in this code:

  • The code in the Form Load event uses random numbers to put some data in the four text boxes.
  • Each text box checks in its MouseDown event to see whether there is any data in the text box. If so, it calls the DoDragDrop method to begin a drag-and-drop operation, and sets a reference to itself in the module-level SourceControl.
  • The DragEnter event of the list box checks the KeyState property to determine whether the Ctrl key is pressed. If so, it displays the copy-drop cursor; otherwise, it displays the move-drop cursor.
  • The DragDrop event of the list box takes the data from the drag and adds it to the list box. If the Ctrl key is pressed and held, it also clears the control that was the source of the data.

Try It Out

To see the drag-and-drop in action, follow these steps:

  1. Press F5 to start the project.
  2. Put the cursor in the first text box control, click and hold the mouse button, and start to move the mouse. You'll see the "no drop" symbol to indicate that you're dragging but are not yet over a drop target.
  3. Drag the cursor to the list box. The cursor will change to the move-drop symbol.
  4. Release the mouse button. The value from the first text box will be added to the list box, and the text box will be cleared.
  5. Put the cursor in the second text box control, hold down the Ctrl key, hold down the mouse button, and start to move the mouse. You'll see the "no drop" symbol to indicate that you're dragging but are not yet over a drop target.
  6. Drag the cursor to the list box. The cursor will change to the copy-drop symbol.
  7. Release the mouse button. The value from the second text box will be added to the list box, but the text box will not be cleared.
  8. Launch WordPad from the Start menu by clicking Programs, clicking Accessories, and then clicking WordPad. Arrange your screen so you can see both the frmDragDrop form and WordPad.
  9. Put the cursor in the third text box control, hold down the mouse button, and start to move the mouse. You'll see the "no drop" symbol to indicate that you're dragging but are not yet over a drop target.
  10. Drag the cursor to the list box. The cursor will change to the copy-drop symbol. Note that WordPad does not implement move-drop, so that you'll get a copy-drop even though you're not holding down the Ctrl key.
  11. Release the mouse button. The value from the third text box will be added to WordPad, but the text box will not be cleared.

Summary

Because all controls in the Windows Forms universe are ultimately descended from the System.Windows.Forms.Control class, the implementation of drag-and-drop is uniform throughout these controls. This makes writing drag-and-drop code in Visual Basic .NET very easy. On the drag side of the equation, you need only call the DoDragDrop method when the appropriate event (usually MouseDown) occurs. On the drop side, you need to set the AllowDrop property to True, then handle the DragEnter and DragDrop events. With a little practice, you should be able to write drag-and-drop code any time you require this functionality.

About the Author

Mike Gunderloy writes about software and raises chickens in eastern Washington state. He's the co-author of Access 2002 Developer's Handbook and author of SQL Server Developer's Guide to OLAP with Analysis Services, both from Sybex. He's been writing code for Microsoft products since the prehistoric pre-Windows era, and has no intention of stopping any time soon.

About Informant Communications Group

Informant Communications Group, Inc. (www.informant.com) is a diversified media company focused on the information technology sector. Specializing in software development publications, conferences, catalog publishing and Web sites, ICG was founded in 1990. With offices in the United States and the United Kingdom, ICG has served as a respected media and marketing content integrator, satisfying the burgeoning appetite of IT professionals for quality technical information.

Copyright © 2002 Informant Communications Group and Microsoft Corporation

Technical editing: PDSA, Inc. or KNG Consulting, Inc.