I wrote something like this for dragging divs on a webpage...
The general approach was to save the coordinates on mousedown, get the coordinates on mouseup, and shift the object's location by the difference.
Here's some example code:
I made a DragInfo
class that keeps the initial mouse coords and initial location. I then store one of these guys in the control's Tag
on the mousedown event:
Public Class DragInfo
Public Property InitialMouseCoords As Point
Public Property InitialLocation As Point
Public Sub New(ByVal MouseCoords As Point, ByVal Location As Point)
InitialMouseCoords = MouseCoords
InitialLocation = Location
End Sub
Public Function NewLocation(ByVal MouseCoords As Point) As Point
Dim loc As New Point(InitialLocation.X + (MouseCoords.X - InitialMouseCoords.X), InitialLocation.Y + (MouseCoords.Y - InitialMouseCoords.Y))
Return loc
End Function
End Class
My test control is just a panel that I put from the toolbox. It could be anything I guess. Here are my mousedown, mousemove, and mouseup event handlers for the panel (Panel1
):
Private Sub Panel1_MouseDown(sender As System.Object, e As System.Windows.Forms.MouseEventArgs) Handles Panel1.MouseDown
Panel1.Tag = New DragInfo(Form.MousePosition, Panel1.Location)
End Sub
Private Sub Panel1_MouseMove(sender As System.Object, e As System.Windows.Forms.MouseEventArgs) Handles Panel1.MouseMove
If Panel1.Tag IsNot Nothing Then
Dim info As DragInfo = CType(Panel1.Tag, DragInfo)
Dim newLoc As Point = info.NewLocation(Form.MousePosition)
If Me.ClientRectangle.Contains(New Rectangle(newLoc, Panel1.Size)) Then Panel1.Location = newLoc
End If
End Sub
Private Sub Panel1_MouseUp(sender As System.Object, e As System.Windows.Forms.MouseEventArgs) Handles Panel1.MouseUp
Panel1.Tag = Nothing
End Sub
There you go! That works. Note that the mousemove method checks if the control is within the form's clientrectangle.
Or, a more generic way to go:
Private Sub MakeDraggable(ByVal Control As Control)
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(ByVal Control As Control)
Control.Tag = New DragInfo(Form.MousePosition, Control.Location)
End Sub
Private Sub Drag(ByVal 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(Form.MousePosition)
If Me.ClientRectangle.Contains(New Rectangle(newLoc, Control.Size)) Then Control.Location = newLoc
End If
End Sub
Private Sub StopDrag(ByVal Control As Control)
Control.Tag = Nothing
End Sub
Now you can just use MakeDraggable(Panel1)
or any other control to make it draggable!
Edit: Both examples now keep the control from being dragged out of bounds.