Snap to grid mouse locking up

徘徊边缘 提交于 2019-12-04 17:04:38

I think I understand where you're coming from. You simply need to be some delta away from the original snap point (the left mouse click) before you snap to the new point.

Here's 50 lines of code illustrating what I mean: (Start a new VB.NET project, add a new module, copy and paste the code, add a reference, to System, System.drawing, and System.Windows.Forms)


Imports System
Imports System.Drawing
Imports System.Windows.Forms

Module modSnap

    Public Const strApplicationTitle As String = "Snap Demo"
    Public frmSnap As SnapForm
    Public ptSnap, ptStart, ptEnd As Point

    Public Class SnapForm
        Inherits Form
        Public Sub New()
            Me.Text = "Snap Demo"
            Me.ClientSize = New Size(800, 600)
            Me.FormBorderStyle = Windows.Forms.FormBorderStyle.FixedSingle
            Me.MaximizeBox = False
            Me.StartPosition = FormStartPosition.CenterScreen
            Me.DoubleBuffered = True
        End Sub
        Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
            MyBase.OnPaint(e)
            e.Graphics.Clear(Color.Black)
            For row As Integer = 20 To 780 Step 20
                For col As Integer = 20 To 580 Step 20
                    e.Graphics.DrawEllipse(Pens.Blue, New Rectangle(row - 2, col - 2, 4, 4))
                Next
            Next
            e.Graphics.DrawLine(Pens.Red, ptStart, ptEnd)
        End Sub
        Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
            MyBase.OnMouseDown(e)
            Dim x As Integer = CInt(e.X / 20) * 20
            Dim y As Integer = CInt(e.Y / 20) * 20
            ptStart = New Point(x, y)
            ptSnap = New Point(x, y)
            Windows.Forms.Cursor.Position = Me.PointToScreen(ptSnap)
        End Sub
        Protected Overrides Sub OnMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs)
            MyBase.OnMouseMove(e)
            If e.Button = Windows.Forms.MouseButtons.Left Then
                Dim x As Integer = CInt(e.X / 20) * 20
                Dim y As Integer = CInt(e.Y / 20) * 20
                ' must be some delta away from original snap point
                If (x < ptSnap.X - 15 Or x > ptSnap.X + 15) Or (y < ptSnap.Y - 15 Or y > ptSnap.Y + 15) Then
                    ptSnap = New Point(x, y)
                    ptEnd = New Point(x, y)
                    Me.Invalidate(False)
                    Windows.Forms.Cursor.Position = Me.PointToScreen(ptSnap)
                End If
            End If
        End Sub
    End Class

    Public Sub main()
        Try
            frmSnap = New SnapForm
            Application.Run(frmSnap)
        Catch ex As Exception
            MessageBox.Show(ex.Message, strApplicationTitle, MessageBoxButtons.OK, MessageBoxIcon.Error)
        Finally
            frmSnap.Dispose()
        End Try
    End Sub

End Module

DonkeyMaster

Don't modify the cursor position. You don't need to.

Instead, draw as if it was snapped to the grid. When the user clicks somewhere, just draw the line from the nearest grid points.

For instance, if the user clicks on (197,198), but you know that the nearest point actually is (200,200), just draw a line to (200,200) instead of (197,198).

And please, don't mess with the actual cursor position.


I don't know if there's some way to hide the mouse cursor. If there is, you can hide it and draw it yourself, without modifying the real position.

Your mouse keeps snapping to the same point if you try to move it -- because it's still closest to that point... If you move the mouse left, move the cursor to the point to the left of the current one instead of recalculating at the current. Apply for the 3 other directions...

I wouldn't recommend this behaviour though, it will cause a lot of irritation. Snap your controls to the grid, not the mouse.

I agree with ruijoel, do not mess with the cursor position. It is better to have a cross or a ring that is drawn at the snap point to show the user which point is the one that will be snapped to at a click event.

For this to work well you may want to look at xor-drawing so that item is erased once you move to a new snap point.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!