I am working on an application which draws a simple dot grid. I would like the mouse to snap between the points on the grid, eventually to draw lines on the grid.
I have a method which takes in the current mouse location (X,Y) and calculates the nearest grid coordinate.
When I create an event and attempt to move the mouse to the new coordinate the whole system becomes jerky. The mouse doesn't snap smoothly between grid points.
I have copied a code sample below to illustrate what I am attempting to do. Does anyone have any advice they could offer me as to how I can eliminate the jumpiness within the mouse movement?
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 < splitContainer1.Panel2.ClientSize.Height; y += gridsize)
{ g.DrawLine(Pens.Black, new Point(x, y), new Point(x + 1, y)); }
}
}
private void splitContainer1_Panel2_MouseMove(object sender, MouseEventArgs e)
{
Point newPosition = new Point();
newPosition = RoundToNearest(gridsize, e.Location);
Cursor.Position = splitContainer1.Panel2.PointToScreen(newPosition);
}
private Point RoundToNearest(int nearestRoundValue, Point currentPoint)
{
Point newPoint = new Point();
int lastDigit;
lastDigit = currentPoint.X % nearestRoundValue;
if (lastDigit >= (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;
}
}
}
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.
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.
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)
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.