vb.netuser-interfaceend-user

allow end-user to move a control


I found a good sample Here, but I have a few problems with it. 1. It is not placing the control to the correct position where the mouse left off becase the control is a big one.

  1. It could be pushed out of the screen.. I want it should stay within the screen boundaries.

This is my code:

   Public Sub Form1_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyControl.MouseMove
    If Not _capturingMoves Then
        Return
    End If
    X = e.X
    Y = e.Y
End Sub

Public Sub Form1_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyControl.MouseUp
    If _capturingMoves Then
        ' Do any final placement
        MyControl.Location = New Point(X, Y)
        _capturingMoves = False
    End If
End Sub

Solution

  • 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.