devxlogo

Implement Drag and Drop in Your Windows Forms Applications

Implement Drag and Drop in Your Windows Forms Applications

n general, when a user drags and drops data from an external application onto your Windows application, you need to determine the structure of the data being passed in and devise the appropriate mechanism to use the data.

However, not many developers take the effort to implement drag and drop functionality in their applications. While it does take considerable effort to implement, adding support for drag and drop to your application will greatly increase its usefulness. This article shows you how to implement drag and drop functionality in your Windows Forms application.

Drag and Drop Event Handlers
To understand how you can drag objects from one control onto another control, you need to become acquainted with a couple of event handlers. Consider the example in Figure 1, which shows the process of dragging an image displayed in one PictureBox control to another PictureBox.

?
Figure 1. Dragging an Image from One PictureBox Control to Another.

To implement the drag and drop feature, you write code for both controls.

Code for Dragged Control
The MouseDown or MouseMove event is probably a good starting point to load the data that is going to be dragged. In this case, you will copy the image stored in the left PictureBox control.

The QueryContinueDrag event allows you to know the outcome of the drag operation, i.e., whether the user eventually drops the item. If the dragging is a move operation and the user successfully executes it, you may need to remove the image on the left PictureBox control.

The control constantly fires the GiveFeedBack event during the drag operation. You can handle this event if you wish to modify the appearance of the mouse pointer.

Code for Control Accepting Drop
When the mouse enters the control that will accept the drop, the control fires the DragEnter event. This is usually the event that you need to service to change the mouse pointer to reflect the action it is performing (such as copy, move, etc). You can also modify the appearance of the control so that it is obvious to the user that the control is a drop target.

While the mouse hovers over the control that will accept at drop, the control fires the DragOver event. The control fires this event continuously as long as the mouse is over the target control. You can use either this event or the DragEnter event to change the appearance of the mouse pointer.

When the mouse leaves the control that accepts a drop, the control fires the DragLeave event. You usually service this event if you modified the control’s appearance during the DragEnter event.

When a user drops an object over the control that accepts a drop, the control fires the DragDrop event, which you can handle appropriately. Using the example from Figure 1, you would load the right PictureBox control with the image that the user drags from the left PictureBox control.

Note that not all controls support the entire set of events just described. For example, the RichTextBox control does not support the DragOver event, so you have to use other supported events to detect drag and drop, such as the DragEnter event.

Also, you can set the AllowDrop property for most controls in the Properties window at design time. However, some controls (such as the PictureBox control) do not expose the AllowDrop property in the Properties window. As such, you need to dynamically set them in code. Also note that IntelliSense will not show the AllowDrop property.

Editor’s Note: This article was first published in the March/April 2008 issue of CoDe Magazine, and is reprinted here by permission.

Drag and Drop Text
Here’s an example application that implements drag and drop. Using Visual Studio 2005, create a new Windows Forms application and name it DragAndDrop. Coding drag and drop operations differs slightly for some controls and for varying data types. This section shows you how to drag and drop some text into a TextBox control.

Populate the default Form1 with a TextBox control (see Figure 2), and set these two TextBox properties as follows:

   Multiline-True   BorderStyle-Fixed3D
?
Figure 2. TextBox Control in Form1.

Switch to the code view for Form1 and declare the following constant:

   Public Class Form1      Const CtrlMask As Byte = 8

In the Form1_Load event, set the TextBox’s AllowDrop property to True:

   Private Sub Form1_Load( _      ByVal sender As System.Object, _      ByVal e As System.EventArgs) _      Handles MyBase.Load         '---set the control to allow drop---      TextBox1.AllowDrop = True   End Sub

Next, you service the DragEnter event. As mentioned earlier, the control fires this event when you drag something into the control. Here, you will determine if the operation is copy or move, (depending on whether the user is holding down the Ctrl key) and then set the mouse pointer accordingly. To check for this special keystroke, you AND the KeyState property with a CtrlMask (defined as a byte with a value of 8). In addition, change the border style of the TextBox control to FixedSingle so that it serves as a visual cue to the user. Here’s the code:

   Private Sub TextBox1_DragEnter( _      ByVal sender As Object, _      ByVal e As _         System.Windows.Forms.DragEventArgs) _         Handles TextBox1.DragEnter      '---if the data to be dropped is a text format---      If (e.Data.GetDataPresent(DataFormats.Text)) Then         '---determine if this is a copy or move---         If (e.KeyState And CtrlMask) = CtrlMask Then            e.Effect = DragDropEffects.Copy         Else            e.Effect = DragDropEffects.Move         End If         '---change the border style of the control---         TextBox1.BorderStyle = BorderStyle.FixedSingle      End If   End Sub

When a user drops the dragged text, you handle the DragDrop event:

   Private Sub TextBox1_DragDrop( _      ByVal sender As Object, _      ByVal e As System.Windows.Forms.DragEventArgs) _      Handles TextBox1.DragDrop         '---if the data to be dropped is a text format---      If (e.Data.GetDataPresent(DataFormats.Text)) Then         '---set the control to display          ' the text being dropped---         TextBox1.Text = e.Data.GetData( _            DataFormats.Text)      End If      '---set the borderstyle back to its original---      TextBox1.BorderStyle = BorderStyle.Fixed3D   End Sub

You can now press F5 to test the application. Figure 3 shows the mouse pointer when a user performs a move (top of the figure) and a copy (bottom of the figure) operation on the TextBox control. To perform a copy operation, simply hold the CTRL key when dragging your mouse. Figure 4 shows the pointer when a user drags an object over a control that does not (bottom of the figure) accept a drop.

?
Figure 3. Move and Copy Mouse Pointers.
?
Figure 4. Dragging Out of a Control.

With the ability to drag and drop text under your belt, you can move on to dragging and dropping images to and from PictureBox controls.

Drag and Drop Images
Using the same project, drag and drop a PictureBox control onto the default Form1 (see Figure 5).

?
Figure 5. Adding a PictureBox Control to Form1.

In the Form1_Load event, set the PictureBox control with the properties as shown below:

   Private Sub Form1_Load( _      ByVal sender As System.Object, _      ByVal e As System.EventArgs) _      Handles MyBase.Load         '---set the control to allow drop---      TextBox1.AllowDrop = True      '---set the control to allow drop---      With PictureBox1         .AllowDrop = True         .BorderStyle = BorderStyle.FixedSingle         .SizeMode = PictureBoxSizeMode.StretchImage      End With      ...

Implementing Drop
As usual, service the DragEnter event so that you can change the mouse pointer appropriately when the mouse hovers over the PictureBox control. The only difference this time is that you check if the data to be dropped onto the PictureBox control is of type image:

   Private Sub PictureBox1_DragEnter( _      ByVal sender As Object, _      ByVal e As System.Windows.Forms. _      DragEventArgs) _      Handles PictureBox1.DragEnter         '---if the data to be dropped is an image format---      If (e.Data.GetDataPresent(DataFormats.Bitmap)) Then         '---determine if this is a copy or move---         If (e.KeyState And CtrlMask) = CtrlMask Then            e.Effect = DragDropEffects.Copy         Else            e.Effect = DragDropEffects.Move         End If         '---change the border style of the control---         PictureBox1.BorderStyle = BorderStyle.Fixed3D      End If   End Sub

For the DragDrop event, you will first verify that the dropped object is of type image and then set the PictureBox control to display the dropped image:

   Private Sub PictureBox1_DragDrop( _      ByVal sender As Object, _      ByVal e As System.Windows.Forms. _      DragEventArgs) _      Handles PictureBox1.DragDrop         '---if the data to be dropped is a bitmap format---      If (e.Data.GetDataPresent(DataFormats.Bitmap)) Then         '---set the control to display          ' the text being dropped---         PictureBox1.Image = e.Data.GetData( _            DataFormats.Bitmap)      End If      '---set the border style back to its original---      PictureBox1.BorderStyle = BorderStyle.FixedSingle   End Sub

Lastly, for the DragLeave event, change the border style of the PictureBox back to its original:

   Private Sub PictureBox1_DragLeave( _      ByVal sender As Object, _      ByVal e As System.EventArgs) _      Handles PictureBox1.DragLeave      '---set the borderstyle back to       ' its original---      PictureBox1.BorderStyle = _         BorderStyle.FixedSingle   End Sub

Press F5 to test the application. You can drag an image from Microsoft Word and drop it onto the PictureBox control, which will then display the image. Interestingly, dragging and dropping an image from WordPad does not cause the PictureBox control to display the image?but you’ll see more about that later.

Implementing Drag
You need to write some code so that you can drag the image displayed in the PictureBox control to someplace else, such as another control or Microsoft Word (or WordPad).

First, handle the MouseDown event handler. The control fires this event when the user clicks the image in the PictureBox control:

   Private Sub PictureBox1_MouseDown( _      ByVal sender As Object, _      ByVal e As System.Windows.Forms. _      MouseEventArgs) _      Handles PictureBox1.MouseDown      If PictureBox1.Image IsNot _         Nothing Then         PictureBox1.DoDragDrop( _            PictureBox1.Image, _            DragDropEffects.Move Or _            DragDropEffects.Copy)      End If   End Sub

Here, you use the DoDragDrop() method of the PictureBox control to copy the image displayed in the PictureBox control. The second parameter of this method indicates the type of drag operations that can occur (in this case it is either a move or copy operation).

You can call the DoDragDrop() method either in the MouseDown or the MouseMove event.

That’s it! You can now drag and drop the image displayed in the PictureBox control to another control. But this time, you’ll find that you can drag the image onto WordPad?but not into Microsoft Word.

Here’s a recap of what you have so far:

  • You can drag a picture from Microsoft Word and drop it onto the PictureBox control. But you cannot drag and drop from WordPad.
  • When you try to drag the image from the PictureBox control onto Word, it does not accept the picture. But you can drag and drop the same image onto WordPad.

To understand why you can drop an image from Word but not from WordPad, you need to modify your application so that you can discover the exact data types that a drop operation passes to the PictureBox control.

Handling Different Data Types
In the DragEnter event you already created, add the line shown below in bold. The GetFormats() method returns the type of data that is passed into the event:

   Private Sub PictureBox1_DragEnter( _      ByVal sender As Object, _      ByVal e As System.Windows.Forms.DragEventArgs) _      Handles PictureBox1.DragEnter         Dim formats As String() = e.Data.GetFormats      '---if the data to be dropped is an image format---      If (e.Data.GetDataPresent(DataFormats.Bitmap)) Then         ...

Set a breakpoint after the line you just added so you can observe the type of data being passed into the event. Press F5 to debug the application and drop an image from Word onto the PictureBox control. Figure 6 shows the data type of the image dragged and dropped from Word.

?
Figure 6. Examining the Data Type of an Image Dropped from Word.
?
Figure 7. Examining the Data Type of an Image Dropped from WordPad.

So, now you can see that one of the possible formats is bitmap; therefore you can safely convert the data into a bitmap image and display it in the PictureBox control. In contrast, if you drag and drop an image from WordPad, the corresponding image type is shown in Figure 7.

This time round, the control does not pass the image data in the bitmap format. Instead, it passes Rich Text Format (RTF).

So, to enable the PictureBox control to accept images dragged and dropped from WordPad, you need to modify the DragEnter event to accept RTF as well as bitmaps:

   Private Sub PictureBox1_DragEnter( _      ByVal sender As Object, _      ByVal e As System.Windows.Forms. _      DragEventArgs) _      Handles PictureBox1.DragEnter         Dim formats As String() = e.Data.GetFormats      '---if the data to be dropped is an image format---      If (e.Data.GetDataPresent(DataFormats.Bitmap)) Then         '---determine if this is a copy or move---         If (e.KeyState And CtrlMask) = CtrlMask Then            e.Effect = DragDropEffects.Copy         Else            e.Effect = DragDropEffects.Move         End If         '---change the border style of the control---         PictureBox1.BorderStyle = BorderStyle.Fixed3D      ElseIf (e.Data.GetDataPresent(DataFormats.Rtf)) Then         '---determine if this is a copy or move---         If (e.KeyState And CtrlMask) = CtrlMask Then            e.Effect = DragDropEffects.Copy         Else            e.Effect = DragDropEffects.Move         End If         '---change the border style of the control---         PictureBox1.BorderStyle = BorderStyle.Fixed3D      End If   End Sub

In addition, you also need to modify the DragDrop event so that you can write your custom code to deal with the particular data format:

   Private Sub PictureBox1_DragDrop( _      ByVal sender As Object, _      ByVal e As System.Windows.Forms. _      DragEventArgs) _      Handles PictureBox1.DragDrop         '---if the data to be dropped is a image format---      If (e.Data.GetDataPresent(DataFormats.Bitmap)) Then         '---set the control to display          ' the text being dropped---         PictureBox1.Image = e.Data.GetData( _            DataFormats.Bitmap)      ElseIf (e.Data.GetDataPresent(DataFormats.Rtf)) Then         '---display the rich text---         Console.WriteLine( _            e.Data.GetData(DataFormats.Rtf))      End If      '---set the borderstyle back to its original---      PictureBox1.BorderStyle = BorderStyle.FixedSingle   End Sub
?
Figure 8. Printing the RTF Content.

Unfortunately, the preceding code simply writes the data of the image (as RTF) to the console window (see Figure 8). To display the actual image in the PictureBox control, you would have to write your own code to extract the image data.

Move versus Copy
The previous example showed how you can copy or move an image from the PictureBox control. In a typical move operation, after copying the image to another control/location, you need to remove the original image. So how do you know when a drop operation has completed? The answer lies in the QueryContinueDrag event.

Add another PictureBox control to Form1 so that Form1 now looks like Figure 9. Using that, you can follow this demonstration showing how to move an image (by drag and drop) from PictureBox1 to PictureBox2.

?
Figure 9. Two PictureBox Controls on Form1.

Configure PictureBox2 in the Form1_Load event as follows:

   Private Sub Form1_Load( _      ByVal sender As System.Object, _      ByVal e As System.EventArgs) _      Handles MyBase.Load      '---set the control to allow drop---      TextBox1.AllowDrop = True      '---set the control to allow drop---      With PictureBox1         .AllowDrop = True         .BorderStyle = BorderStyle.FixedSingle         .SizeMode = PictureBoxSizeMode.StretchImage      End With      '---set the control to allow drop---      With PictureBox2         .AllowDrop = True         .BorderStyle = BorderStyle.FixedSingle         .SizeMode = PictureBoxSizeMode.StretchImage      End With      ...

Add the code shown in Listing 1 to PictureBox2 to support dropping.

For a move operation, you need to remove the image in PictureBox1 after the user has moved it to PictureBox2. To do this, you need to service the QueryContinueDrag event of PictureBox1. The control fires this event after you drag and drop an image from PictureBox1. In that event code, you can determine whether the operation is a move, and if it is, delete the image from PictureBox1:

   Private Sub PictureBox1_QueryContinueDrag( _      ByVal sender As Object, _      ByVal e As _      System.Windows.Forms.QueryContinueDragEventArgs) _      Handles PictureBox1.QueryContinueDrag         If e.Action = DragAction.Drop Then         If (e.KeyState And CtrlMask) <> CtrlMask Then            '---a move operation---            PictureBox1.Image = Nothing         End If      End If   End Sub

You can now test the code. Press F5 in Visual Studio 2005 and then drag and drop an image onto PictureBox1. Next, drag the image that’s now in PictureBox1 and drop it onto PictureBox2. Notice that the image in PictureBox1 is now gone. If you instead perform a copy operation (by holding down the CTRL key) while dragging the image from PictureBox1 to PictureBox2; the code that services the QueryContinueDrag event merely copies the image and does not remove it.

Note that using the QueryContinueDrag event to remove an item that a user has moved is not a foolproof method. If you abort the move operation (such as dropping the image outside PictureBox2), the control will still remove the picture. In other words, using the QueryContinueDrag event, you have no idea where the user moved (or dropped) the item, or whether the user aborted the operation.

Drag and Drop Files
One common operation in Windows applications is dragging and dropping files onto applications. For example, you probably drag and drop files onto folders, or drag music files onto Windows Media player so that you can play them immediately.

You can modify the sample application so that users can drag an image file from Windows Explorer and drop it onto the PictureBox control in two steps:

  • First, modify the DragEnter event (see Listing 2). The data type for a file that is dragged from the Windows Explorer is FileDrop, so the code in Listing 2 checks for that data type in the DragEnter event handler.
  • Next, modify the DragDrop event as shown in Listing 3, so that you can manually open up the image file and display its content in the PictureBox control.

That’s it! You can now drag an image file from Windows Explorer and drop it onto the PictureBox control and view its content. Note that in this particular implementation, users can drop one or more files onto the PictureBox control. For multiple files, the example application displays each photo one by one with a two-second interval.

Implementing Drag and Drop for Special Controls
Most Windows Forms controls support the set (or a subset) of the events described in this article for drag and drop operations. However, what happens if the control you want to enable for drag and drop does not support the standard list of events? A good example is the Windows Media Player ActiveX control. You might want to embed the Windows Media Player control in a Windows application so that users can simply drag and drop media files onto it to play. Unfortunately, the Windows Media Player ActiveX control by itself does not support events like DragEnter and DragDrop; therefore there’s no easy way to implement drag and drop directly.

You can work around the problem by wrapping the ActiveX control using a User control. To do that, add a new User Control item (right-click the project name in Solution Explorer and select Add ? New Item? ? select User Control) to the existing project. Name the file MediaPlayer.vb.

Add the Windows Media Player to your Toolbox. To do that, right-click the Toolbox and select “Choose Items?.” In the Choose Toolbox Items dialog box, click the COM Components tab, and check the Windows Media Player object (see Figure 10). Click OK to add the Windows Media Player control to the Toolbox.

?
Figure 10. Adding the Windows Media Player ActiveX Control to the Toolbox.
?
Figure 11. Populate the User Control with the Windows Media Player Control.

Drag the Windows Media Player control from the Toolbox and drop it onto the MediaPlayer.vb design surface (see Figure 11).

The MediaPlayer control should now appear in the toolbox (see Figure 12).

?
Figure 12. The MediaPlayer Control in the User Control.
?
Figure 13. Adding the MediaPlayer Control to Form1.

Drag and drop the MediaPlayer user control onto Form1 (see Figure 13).

In the code view for MediaPlayer.vb, add the following code:

   Public Class MediaPlayer   Private _URL As String      Public Property URL() As String         Get            Return _URL         End Get         Set(ByVal value As String)            _URL = value            AxWindowsMediaPlayer1. _               URL = _URL         End Set      End Property   End Class

Essentially you expose the URL property to let the user of this control set the URL of the media file to play.

Switch to the code-behind of Form1 and handle the DragEnter event of the MediaPlayer user control as follows:

   Private Sub MediaPlayer1_DragEnter( _      ByVal sender As Object, _      ByVal e As System.Windows.Forms.DragEventArgs) _      Handles MediaPlayer1.DragEnter      '---if the data to be dropped is       ' an filedrop format---      If (e.Data.GetDataPresent( _         DataFormats.FileDrop)) Then         '---determine if this is a copy or move---         If (e.KeyState And CtrlMask) = CtrlMask Then            e.Effect = DragDropEffects.Copy         Else            e.Effect = DragDropEffects.Move         End If      End If   End Sub

Finally, handle the DragDrop event so that you can play the media file dropped by the user:

   Private Sub MediaPlayer1_DragDrop( _      ByVal sender As Object, _      ByVal e As System.Windows.Forms. _      DragEventArgs) _      Handles MediaPlayer1.DragDrop         If (e.Data.GetDataPresent( _         DataFormats.FileDrop)) Then         Dim files() As String         '---get all the file names---         files = e.Data.GetData( _            DataFormats.FileDrop)         If files.Length > 0 Then            '---load only the first file---            files(0) = UCase(files(0))            If files(0).EndsWith(."WMV") Then               '---get the media player to play the                ' first file---               MediaPlayer1.URL = files(0)            End If         End If      End If   End Sub
?
Figure 14. Dragging and Dropping a Media File onto Form1.

Note that because the user can drop multiple files onto the control, you will load only the first file using the MediaPlayer control.

Figure 14 shows the MediaPlayer control hosted in a Windows Form playing the file dropped onto it.

Dragging and Dropping Custom Objects
So far, you’ve seen how to use several of the various data types specified in the DataFormats class: Bitmap, CommaSeparatedValue, Dib, Dif, EnhancedMetafile, FileDrop, Html, Locale, MetafilePict, OemText, Palette, PenData, Riff, Rtf, Serializable, StringFormat, SymbolicLink, Text, Tiff, UnicodeText, and WaveAudio. But what happens if you want to drag and drop data of a type that’s not listed? For example, you might want to drag an item from a ListView control. In this case, the DragEnter event will look something like this:

   If (e.Data.GetDataPresent _      ("System.Windows.Forms. _      ListViewItem()")) Then      '---determine if this is a copy       '---or move---      If (e.KeyState And CtrlMask) =          CtrlMask Then         e.Effect =          DragDropEffects.Copy      Else         e.Effect =          DragDropEffects.Move      End If

The MouseDown event handler will now look like this:

   Control.DoDragDrop(New _         DataObject("System.Windows.Forms. _      ListViewItem()", Items), _      DragDropEffects.Move Or _      DragDropEffects.Copy)

As you can see, it isn’t terribly difficult to implement drag and drop functionality in your Windows application. All you need is to understand the type of data you want to support and make the necessary provisions for dealing with that particular data type.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist