Most document-based applications typically allow to open a document file in two ways: with the Open File menu command / toolbar button, or by dragging and dropping the file from Windows Explorer to the application’s window. This works with MS Word, Winzip and many other applications. Implementing the same feature in your own Windows Forms application is a breeze, and involves the following three steps:
1) Set the property AllowDrop to True for the control that you want to use as the target of the drag&drop operation. This is usually a listview, textbox or another control that takes the whole form’s space, and that will visualize the file’s content, or do some other operation with it.
2) When you drag something (a control, a treeview’s node, or a file in this case) over a target control, the drop will always be denied, until explicitly set. To enable the drop of the dragged file, you must handle the target control’s DragEnter event, check if the type of dragged data is the correct type (i.e. it is a file) and set the Effect property of the event’s e parameter, that is also used to show a proper mouse cursor. (The mouse cursor is in fact different if you’re going to copy or move the content.) In this example we use a ListBox as target control, and the code for the DragEnter event is as follows:
Private Sub ListBox1_DragEnter(ByVal sender As Object, _ ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox1.DragEnter ' if the dragged stuff is files, enable the drop operation on this control If e.Data.GetDataPresent(DataFormats.FileDrop) Then e.Effect = DragDropEffects.Copy End IfEnd Sub
At this point what’s left is to actually handle the drop of the files, and retrieve the file names to open the documents, or work with them in some other ways. To do this we handle the target control’s DragDrop event. Within this event we first check if the data dropped over the control are files – in this case it is not strictly necessary in reality, because we’ve already done the check in DragEnter, and enabled the drop only if the data type is correct, but in general we may want to allow the drag&drop of different types of data, so we must check the data type and perform different operations according to it. If the data are files, the file names are internally stored as an array of String. I say internally because the data is exposed as a generic Object, so if you use Option Strict On (and you should…) you must explicitly cast to String(). Once you have the file names into the string array, you can do what you want with them. The following code snippet shows how to retrieve the file names and add them to the ListBox:
Private Sub ListBox1_DragDrop(ByVal sender As Object, _ ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox1.DragDrop ' check whether the dragged stuff is actually files If e.Data.GetDataPresent(DataFormats.FileDrop) Then ' copy the name of the dragged files into a string array Dim draggedFiles As String() = CType(e.Data.GetData _ (DataFormats.FileDrop), String()) ' add all the file names to the listbox For Each filename As String In draggedFiles ListBox1.Items.Add(filename) Next End IfEnd Sub
That’s it, a few lines of code! It was much more difficult in VB6, as you had to use subclassing, low level Windows messages and extract the strings from a buffer.