我正在开发一个绘制简单点网格的应用程序。我希望鼠标在网格上的点之间捕捉,最终在网格上绘制线条。
我有一个方法,它接收当前鼠标位置(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;
}
}
}
答案 0 :(得分:6)
不要修改光标位置。你不需要。
相反,绘制就像它被捕捉到网格一样。当用户点击某处时,只需从最近的网格点绘制线条。
例如,如果用户点击(197,198),但您知道最近的点实际上是(200,200),则只需绘制一条线到(200,200)而不是(197,198)。
请不要弄乱实际的光标位置。
我不知道是否有某种方法可以隐藏鼠标光标。如果有,你可以隐藏它并自己绘制,而不修改实际位置。
答案 1 :(得分:3)
如果你试图移动它,你的鼠标会一直捕捉到同一个点 - 因为它仍然最接近那个点......如果你向左移动鼠标,则将光标移动到当前一个点的左边。在当前重新计算。申请其他3个方向......
我不会推荐这种行为,但会引起很多烦恼。将控件捕捉到网格,而不是鼠标。
答案 2 :(得分:2)
我想我明白你的来源。在捕捉到新点之前,您只需要远离原始捕捉点(鼠标左键单击)一些三角形。
以下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
答案 3 :(得分:0)
我同意ruijoel,不要弄乱光标位置。 最好在捕捉点绘制一个十字或一个环,以向用户显示哪个点是在点击事件中将被捕捉的点。
为了使其正常工作,您可能需要查看xor-drawing,以便在移动到新的捕捉点时删除该项目。