Public Class Draggable

    Public form As Form

    Public Event ControlDropped(ctrl As Control)

    Public Sub MakeDraggable(Control As Control, ByRef _form As Form)
        form = _form
        AddHandler Control.MouseDown, Sub(sender As Object, e As MouseEventArgs) StartDrag(Control)
        AddHandler Control.MouseMove, Sub(sender As Object, e As MouseEventArgs) Drag(Control)
        AddHandler Control.MouseUp, Sub(sender As Object, e As MouseEventArgs) StopDrag(Control)
    End Sub

    Private Sub StartDrag(Control As Control)
        Control.Tag = New DragInfo(Control.MousePosition, Control.Location, Control.Tag)
    End Sub

    Private Sub Drag(Control As Control)
        If Control.Tag IsNot Nothing AndAlso TypeOf Control.Tag Is DragInfo Then
            Dim info As DragInfo = CType(Control.Tag, DragInfo)
            Dim newLoc As Point = info.NewLocation(Control.MousePosition)
            'Raster 
            newLoc.X = Math.Round(newLoc.X / 10, 0) * 10
            newLoc.Y = Math.Round(newLoc.Y / 10, 0) * 10
            If form.ClientRectangle.Contains(New Rectangle(newLoc, Control.Size)) Then Control.Location = newLoc
        End If
    End Sub

    Private Sub StopDrag(Control As Control)
        If Control.Tag IsNot Nothing AndAlso TypeOf Control.Tag Is DragInfo Then
            Dim info As DragInfo = CType(Control.Tag, DragInfo)
            Control.Tag = info.OldTag
            RaiseEvent ControlDropped(Control)
        End If
    End Sub

End Class
