Accrocher à la souris de la grid se verrouiller

Je travaille sur une application qui dessine une simple grid de points. Je voudrais que la souris se casse entre les points de la grid, pour éventuellement tracer des lignes sur la grid.

J’ai une méthode qui prend l’emplacement actuel de la souris (X, Y) et calcule les coordonnées de grid les plus proches.

Lorsque je crée un événement et que j’essaie de déplacer la souris vers la nouvelle coordonnée, tout le système devient saccadé. La souris ne s’enclenche pas facilement entre les points de la grid.

J’ai copié un exemple de code ci-dessous pour illustrer ce que je tente de faire. Quelqu’un a-t-il un conseil à me donner quant à la façon dont je peux éliminer la nervosité dans le mouvement de la souris?


using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace GridTest { public partial class Form1 : Form { Graphics g; const int gridsize = 20; public Form1() { InitializeComponent(); g = splitContainer1.Panel2.CreateGraphics(); splitContainer1.Panel2.Invalidate(); } private void splitContainer1_Panel2_Paint(object sender, PaintEventArgs e) { Drawgrid(); } private void Drawgrid() { for (int x = 0; x < splitContainer1.Panel2.ClientSize.Width; x += gridsize) { for (int y = 0; y = (nearestRoundValue/2)) { newPoint.X = currentPoint.X - lastDigit + nearestRoundValue; } else { newPoint.X = currentPoint.X - lastDigit; } lastDigit = currentPoint.Y % nearestRoundValue; if (lastDigit >= (nearestRoundValue / 2)) { newPoint.Y = currentPoint.Y - lastDigit + nearestRoundValue; } else { newPoint.Y = currentPoint.Y - lastDigit; } return newPoint; } } } 

Je pense que je comprends d’où vous venez. Vous devez simplement être éloigné du point d’accrochage d’origine (clic gauche) avant de vous accrocher au nouveau point.

Voici 50 lignes de code illustrant ce que je veux dire: (Démarrer un nouveau projet VB.NET, append un nouveau module, copier / coller le code, append une référence à System, System.drawing et System.Windows.Forms)

 Imports System Imports System.Drawing Imports System.Windows.Forms Module modSnap Public Const strApplicationTitle As Ssortingng = "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(eX / 20) * 20 Dim y As Integer = CInt(eY / 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(eX / 20) * 20 Dim y As Integer = CInt(eY / 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
Imports System Imports System.Drawing Imports System.Windows.Forms Module modSnap Public Const strApplicationTitle As Ssortingng = "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(eX / 20) * 20 Dim y As Integer = CInt(eY / 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(eX / 20) * 20 Dim y As Integer = CInt(eY / 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 

Ne modifiez pas la position du curseur. Tu n’as pas besoin de.

Au lieu de cela, dessinez comme si elle était accrochée à la grid. Lorsque l’utilisateur clique quelque part, tracez simplement la ligne à partir des points de grid les plus proches.

Par exemple, si l’utilisateur clique sur (197,198), mais que vous savez que le point le plus proche est réellement (200,200), tracez simplement une ligne sur (200,200) au lieu de (197,198).

Et s’il vous plaît, ne jouez pas avec la position réelle du curseur.


Je ne sais pas s’il y a moyen de cacher le curseur de la souris. Si c’est le cas, vous pouvez le cacher et le dessiner vous-même, sans modifier la position réelle .

Si vous essayez de le déplacer, votre souris continue de s’accrochant au même point – car il est toujours le plus proche de ce point … Si vous déplacez la souris vers la gauche, déplacez le curseur sur le point situé à gauche du point actuel au lieu de recalculer à le courant. Appliquer pour les 3 autres directions …

Je ne recommanderais pas ce comportement cependant, cela causera beaucoup d’irritation. Alignez vos contrôles sur la grid, pas sur la souris.

Je suis d’accord avec ruijoel, ne plaisante pas avec la position du curseur. Il est préférable d’avoir une croix ou un anneau dessiné au point d’accrochage pour indiquer à l’utilisateur le point sur lequel il sera capturé lors d’un événement clic.

Pour que cela fonctionne bien, vous voudrez peut-être examiner xor-drawing de manière à ce que l’élément soit effacé une fois que vous avez déplacé le point d’accrochage.