Drag & drop

This part of the Mono Visual Basic Winforms tutorial will be dedicated to the drag & drop operations.

In computer graphical user interfaces, drag-and-drop is the action of (or support for the action of) clicking on a virtual object and dragging it to a different location or onto another virtual object. In general, it can be used to invoke many kinds of actions, or create various types of associations between two abstract objects. (Wikipedia)

Drag and drop functionality is one of the most visible aspects of the graphical user interface. Drag and drop operation enables you to do complex things intuitively.

Dragging a button

In the first example, we will do the drag & drop operation on the button control. The example does the job outside the drag & drop protocol.

' ZetCode Mono Visual Basic Winforms tutorial
'
' In this program we drag & drop
' a button control
'
' author jan bodnar
' last modified May 2009
' website www.zetcode.com

Imports System.Windows.Forms
Imports System.Drawing


Public Class WinVBApp
    Inherits Form

    Private isDragging As Boolean = False
    Private oldX As Integer
    Private oldY As Integer
    Private button As Button


    Public Sub New

        Me.Text = "Drag & Drop button"
        Me.Size = New Size(270, 180)
       
        Me.InitUI
       
        Me.CenterToScreen

    End Sub
    
    Private Sub InitUI
    
        button = New Button
        button.Parent = Me
        button.Cursor = Cursors.Hand
        button.Text = "Button"
        button.Location = New Point(20, 20)

        AddHandler button.MouseDown, AddressOf Me.OnMouseDown
        AddHandler button.MouseUp, AddressOf Me.OnMouseUp
        AddHandler button.MouseMove, AddressOf Me.OnMouseMove

    End Sub
    
    Private Sub OnMouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)
        isDragging = True
        oldX = e.X
        oldY = e.Y
    End Sub

    Private Sub OnMouseMove(ByVal sender As Object, ByVal e As MouseEventArgs)
        If isDragging
            button.Top = button.Top + (e.Y - oldY)
            button.Left = button.Left + (e.X - oldX)
        End If
    End Sub
    
    Private Sub OnMouseUp(ByVal sender As Object, ByVal e As MouseEventArgs)
        isDragging = False
    End Sub
    

    Public Shared Sub Main
        Application.Run(New WinVBApp)
    End Sub
   
End Class

The code example puts a regular button control on the form container. By clicking on the button surface and simultaneously dragging it with a mouse we can relocate the button.

There are some supporting variables in our example. The isDragging variable tells us, whether we are in the process of dragging an object. The oldX and oldY variables store the x, y coordinates just before the dragging process begins.

AddHandler button.MouseDown, AddressOf Me.OnMouseDown
AddHandler button.MouseUp, AddressOf Me.OnMouseUp
AddHandler button.MouseMove, AddressOf Me.OnMouseMove

We plug in three different mouse handlers for our button. They implement three different stages of the drag & drop process. The process begins, when we click on the button. This is handled by the OnMouseDown method. The second part is the movement. This is when we move the object to a new position. It is handled in the OnMouseMove method. The final part is when the process stops. It happens when we release the mouse button. The appropriate task is delegated to the OnMouseUp method.

Private Sub OnMouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)
    isDragging = True
    oldX = e.X
    oldY = e.Y
End Sub

The OnMouseDown method implements the first part of the process. It sets three necessary variables.

Private Sub OnMouseMove(ByVal sender As Object, ByVal e As MouseEventArgs)
    If isDragging
        button.Top = button.Top + (e.Y - oldY)
        button.Left = button.Left + (e.X - oldX)
    End If
End Sub

In the OnMouseMove method, we relocate the button. We calculate the difference between the stored x, y coordinates and the new coordinates of the mouse pointer. The difference is added to the Top and Left properties of the button, thus moving it to a new position.

Dragging a button
Figure: Dragging a button

Dragging Text

In the previous example, we did drag & drop on the control. Next we will do a drag & drop operation on the textual data. Here we will use the drag & drop protocol provided by the Winforms library.

Drag & drop operation is a standardized communication protocol in Winforms. We have two basic objects. The drag source and the drop target.

' ZetCode Mono Visual Basic Winforms tutorial
'
' In this program we drag & drop
' text
'
' author jan bodnar
' last modified May 2009
' website www.zetcode.com

Imports System.Windows.Forms
Imports System.Drawing


Public Class WinVBApp
    Inherits Form
    
    Private txtBox As TextBox
    Private btn As Button

    Public Sub New

       Me.Text = "Drag & Drop text"
       Me.Size = New Size(250, 200)
       
       Me.InitUI
       
       Me.CenterToScreen

    End Sub
    
    Private Sub InitUI
    
        btn = New Button
        txtBox = New TextBox
        Me.SuspendLayout

        btn.AllowDrop = True
        btn.Location = New Point(150, 50)
        txtBox.Location = New Point(15, 50)

        Me.Controls.Add(btn)
        Me.Controls.Add(txtBox)
        Me.ResumeLayout

        AddHandler btn.DragEnter, AddressOf Me.OnDragEnter
        AddHandler btn.DragDrop, AddressOf Me.OnDragDrop
        AddHandler txtBox.MouseDown, AddressOf Me.OnMouseDown

    End Sub
    
    Private Sub OnDragEnter(ByVal sender As Object, ByVal e As DragEventArgs)
        e.Effect = DragDropEffects.Copy
    End Sub

    Private Sub OnDragDrop(ByVal sender As Object, ByVal e As DragEventArgs)
        sender.Text = e.Data.GetData(DataFormats.Text)
    End Sub

    Private Sub OnMouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)
        sender.DoDragDrop(sender.Text, DragDropEffects.Copy)
    End Sub
    

    Public Shared Sub Main
        Application.Run(New WinVBApp)
    End Sub
   
End Class

We have two controls on the form. A button and a text box. We will drag text from the text box and drop it on the button.

btn.AllowDrop = True

We set the AllowDrop property to true. Dropping is not enabled by default.

AddHandler btn.DragEnter, AddressOf Me.OnDragEnter
AddHandler btn.DragDrop, AddressOf Me.OnDragDrop
AddHandler txtBox.MouseDown, AddressOf Me.OnMouseDown

Again, the drag & drop process is divided into three steps. We have three methods for each particular step.

Private Sub OnDragEnter(ByVal sender As Object, ByVal e As DragEventArgs)
    e.Effect = DragDropEffects.Copy
End Sub

The DragEnter event is launched when the mouse pointer enters the area of the drop target control. The Effect property must be set. The DragDropEffects of the drag source and drop target must be equal. Otherwise the operation will not work.

Private Sub OnDragDrop(ByVal sender As Object, ByVal e As DragEventArgs)
    sender.Text = e.Data.GetData(DataFormats.Text)
End Sub

Finally we have the OnDragDrop method. Here we get the data from the event object and set it to the button Text property.

Private Sub OnMouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)
    sender.DoDragDrop(sender.Text, DragDropEffects.Copy)
End Sub

In the OnMouseDown method we initialize the drap & drop process. We initiate the process with the DoDragDrop method. The DragDropEffects.Copy parameter specifies the type of the operation. Esentially, we can either copy the text or move it during the drag & drop operation.

Drag & drop of text
Figure: Drag & drop of text

Dragging Image

In our last example, we will drag & drop image on the form.

' ZetCode Mono Visual Basic Winforms tutorial
'
' In this program we drag & drop
' an image
'
' author jan bodnar
' last modified May 2009
' website www.zetcode.com

Imports System.Windows.Forms
Imports System.Drawing


Public Class WinVBApp
    Inherits Form

    Private IsDragging As Boolean = False
    Private oldX As Integer
    Private oldY As Integer
    
    Private dropRect As Rectangle
    Private picBox As PictureBox
    Private image As Bitmap
    Private brsh As Brush

    Public Sub New

        Me.Text = "Drag & Drop image"
        Me.Size = New Size(350, 250)
       
        Me.InitUI
       
        Me.CenterToScreen

    End Sub
    
    Private Sub InitUI
    
        isDragging = False
        dropRect = New Rectangle(10, 10, 200, 160)
        brsh = Brushes.Gray
        picBox = New PictureBox
        Me.LoadImage

        picBox.Parent = Me
        picBox.Location = New Point(100, 50)
        picBox.Size = New Size(image.Width, image.Height)
        picBox.Image = image
        picBox.Cursor = Cursors.Hand

        AddHandler Me.Paint, AddressOf Me.OnPaint

        AddHandler picBox.MouseDown, AddressOf Me.OnMouseDown        
        AddHandler picBox.MouseMove, AddressOf Me.OnMouseMove
        AddHandler picBox.MouseUp, AddressOf Me.OnMouseUp

    End Sub
    
    Private Sub LoadImage
    
      Try 
          image = New Bitmap("image.jpg")
      Catch 
          Console.WriteLine("Error reading image")
          Environment.Exit(1)
      End Try
      
    End Sub  
    
    Private Sub OnMouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)
        isDragging = True
        oldX = e.X
        oldY = e.Y
    End Sub

    Private Sub OnMouseMove(ByVal sender As Object, ByVal e As MouseEventArgs)
        If isDragging
            picBox.Top = picBox.Top + (e.Y - oldY)
            picBox.Left = picBox.Left + (e.X - oldX)
        End If
    End Sub
    
    Private Sub OnMouseUp(ByVal sender As Object, ByVal e As MouseEventArgs)
    
        isDragging = False

        If dropRect.Contains(picBox.Bounds)
            brsh = Brushes.Gold
        Else 
            brsh = Brushes.Gray
        End If

        Me.Refresh
        
    End Sub
    
    Private Sub OnPaint(ByVal sender As Object, ByVal e As PaintEventArgs)
        Dim g As Graphics = e.Graphics
        g.FillRectangle(brsh, dropRect)
    End Sub
    
    
    Public Shared Sub Main
        Application.Run(New WinVBApp)
    End Sub
   
End Class

In our example we have a PictureBox and we draw a gray rectangle. If we drop the picture inside the rectangle, the color of the rectangle changes to gold.

brsh = Brushes.Gray

The brsh variable holds the brush of the rectangle. It is a gray color by default.

Private Sub LoadImage

  Try 
      image = New Bitmap("image.jpg")
  Catch 
      Console.WriteLine("Error reading image")
      Environment.Exit(1)
  End Try
 
End Sub  

The LoadImage method loads a bitmap for the PictureBox control.

If dropRect.Contains(picBox.Bounds)
    brsh = Brushes.Gold
Else 
    brsh = Brushes.Gray
End If

In the OnMouseUp method, we determine the brush of the rectangle. If the bounds of the picture box are inside the rectangle, the brush is of gold color; gray otherwise.

Me.Refresh

We must call the Refresh method to activate the new brush color.

Drag & drop image
Figure: Drag & drop image

This chapter was dedicated to drag & drop operations using the Mono Winforms library with the Visual Basic language.