2008-12-11 60 views
2

我正在绘制一个简单点网格的应用程序。我希望鼠标在网格上的点之间对齐,最终在网格上绘制线条。对齐网格鼠标锁定

我有一个方法,它接受当前鼠标位置(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; 
     } 
    } 
} 

回答

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

您的鼠标保持捕捉到同一点,如果你尝试移动它 - 因为它仍然是最接近这一点......如果你向左移动鼠标,将光标移动到指向而不是在当前重新计算。申请3个其他方向...

虽然我不会推荐这种行为,但会引起很多刺激。将控件捕捉到网格,而不是鼠标。

6

请勿修改光标位置。你不需要。

取而代之的是,好像它被捕捉到网格。当用户点击某处时,只需从最近的网格点画出线条即可。例如,如果用户点击(197,198),但您知道最近的点实际上是(200,200),则只需画一条线(200,200)而不是(197,198)即可。

而且请不要乱动实际光标位置。


我不知道是否有某种方法可以隐藏鼠标光标。如果有的话,您可以隐藏它并自己绘制,而不修改实际位置

0

我同意ruijoel,不要弄乱光标位置。 最好在捕捉点绘制一个十字或一个圆环,以向用户显示在点击事件时哪个点将被捕捉到。

为了使其运行良好,您可能需要查看xor-drawing,以便在移动到新的捕捉点时清除物件。