Alex Gordon
Alex Gordon

Reputation: 60731

dragging during runtime

the user has the option of dragging several pictureboxes around the form. when he lets go of the mouse, the picturebox will take on a new position on the form. this i have done succesfully thanks to the stackoverflow community.

i would like to implement the following:

on mouseup, if the picturebox position is within some amount maybe 50 or 100 (i dont know what units VB.net) uses, i would like it to be dropped exactly in a defined position. sort of like if you play checkers on yahoo games, you dont have to place the piece exactly on the square only approximately.

please help me with a solution in vb.net

Upvotes: 0

Views: 1228

Answers (1)

Fredrik Mörk
Fredrik Mörk

Reputation: 158309

This would work well, I think (cellSize is the "resolution" to which the control will "snap", assuming that each cell is square).

Prerequisites: you will need to have a PictureBox (or some other control) that you want to move around on your Form. Put the sample code below in your form's code and attach the MouseDown, MouseMove and MouseUp events of that control to these event handlers. You can attach the events using the property grid (click the events button, select the event, and use the combo box to select the corresponding event handler).

VB.NET:

Private Sub SetControlPosition(ByVal control As Control, ByVal targetPoint As Point, ByVal cellSize As Integer)
    Dim roundedLocation As New Point(CInt((Math.Round(CSng(targetPoint.X) / cellSize) * cellSize)), CInt((Math.Round(CSng(targetPoint.Y) / cellSize) * cellSize)))
    control.Location = roundedLocation
End Sub

If you want the control location to snap to some specific pre-defined locations, you can do like this instead (_allowedLocations defines two allowed locations; x=50, y=50 and x=500, y=500):

Private _allowedLocations As Point() = {New Point(50, 50), New Point(500, 500), New Point(700, 100)}
Private Sub SetControlPosition(ByVal control As Control, ByVal targetPoint As Point, ByVal cellSize As Integer)
    Dim shortestDistance As Integer = Integer.MaxValue
    Dim nearestLocationIndex As Integer = -1
    
    For i As Integer = 0 To _allowedLocations.Length - 1
        Dim width As Integer = targetPoint.X - _allowedLocations(i).X
        Dim height As Integer = targetPoint.Y - _allowedLocations(i).Y
        Dim distance As Integer = CInt(Math.Sqrt(Math.Pow(width, 2) + Math.Pow(height, 2)))
        If distance < shortestDistance Then
            shortestDistance = distance
            nearestLocationIndex = i
        End If
    Next
    control.Location = _allowedLocations(nearestLocationIndex)
End Sub

Example code calling the method (including moving the control with the mouse):

Private _mouseDownLocation As Point = Point.Empty
Private Sub PictureBox_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)
    If (e.Button And MouseButtons.Left) = System.Windows.Forms.MouseButtons.Left Then
        _mouseDownLocation = e.Location
    End If
End Sub

Private Sub PictureBox_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs)
    If (e.Button And MouseButtons.Left) = System.Windows.Forms.MouseButtons.Left Then
        Dim target As Control = DirectCast(sender, Control)
        target.Location = New Point(target.Location.X + e.Location.X - _mouseDownLocation.X, target.Location.Y + e.Location.Y - _mouseDownLocation.Y)
    End If
End Sub

Private Sub PictureBox_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs)
    If (e.Button And MouseButtons.Left) = System.Windows.Forms.MouseButtons.Left Then
        Dim target As Control = DirectCast(sender, Control)
        ' Snap the control in place, to nearest 100x100 corner '
        SetControlPosition(target, target.Location, 100)
    End If
End Sub

The SetControlPosition method in C# (as an extra bonus):

private void SetControlPosition(Control control, Point targetPoint, int cellSize)
{
    Point roundedLocation = new Point(
        (int)(Math.Round((float)targetPoint.X / cellSize) * cellSize),
        (int)(Math.Round((float)targetPoint.Y / cellSize) * cellSize)
        );
    control.Location = roundedLocation;
}

Upvotes: 2

Related Questions