Я работаю над приложением, которое рисует простую точечную сетку. Я хотел бы, чтобы мышь щелкала между точками на сетке, чтобы в конечном итоге рисовать линии на сетке.
У меня есть метод, который принимает текущее местоположение мыши (X, Y) и вычисляет ближайшую координату сетки.
Когда я создаю событие и пытаюсь переместить мышь в новую координату, вся система становится дерганной. Мышь не переключается между точками сетки плавно.
Я скопировал образец кода ниже, чтобы проиллюстрировать, что я пытаюсь сделать. Есть ли у кого-нибудь какой-нибудь совет, который они могли бы мне предложить, как я могу устранить резкость при движении мыши?
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;
}
}
}





Ваша мышь продолжает привязку к той же точке, если вы пытаетесь ее переместить - потому что она все еще ближе всего к этой точке ... Если вы переместите мышь влево, переместите курсор в точку слева от текущей, а не пересчитываете электрический ток. Подать заявку на 3 других направления ...
Я бы не рекомендовал такое поведение, это вызовет много раздражения. Привязывайте элементы управления к сетке, а не к мыши.
Не меняйте положение курсора. Тебе это не нужно.
Вместо этого рисовать, как если бы он был привязан к сетке. Когда пользователь куда-то щелкает, просто проведите линию от ближайших точек сетки.
Например, если пользователь нажимает (197 198), но вы знаете, что ближайшая точка на самом деле (200 200), просто проведите линию до (200 200) вместо (197 198).
И, пожалуйста, не связывайтесь с позицией курсора действительный.
Я не знаю, есть ли способ скрыть курсор мыши. Если есть, можете спрятать и нарисовать самостоятельно, без изменения реальной позиции.
Я согласен с ruijoel, не связывайтесь с позицией курсора. Лучше иметь крест или кольцо, которое рисуется в точке привязки, чтобы показать пользователю, какая точка является той, к которой будет привязана при событии щелчка.
Чтобы это работало хорошо, вы можете посмотреть на xor-drawing, чтобы этот элемент стирался при переходе к новой точке привязки.
Думаю, я понимаю, откуда вы. Вам просто нужно немного отклониться от исходной точки привязки (щелчок левой кнопкой мыши), прежде чем привязаться к новой точке.
Вот 50 строк кода, иллюстрирующих то, что я имею в виду: (Запустите новый проект VB.NET, добавьте новый модуль, скопируйте и вставьте код, добавьте ссылку в System, System.drawing и 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