Привязка к сетке мыши блокировка

Я работаю над приложением, которое рисует простую точечную сетку. Я бы хотел, чтобы мышь щелкала между точками на сетке, в конечном итоге рисуя линии на сетке.

У меня есть метод, который принимает текущее местоположение мыши (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;
        }
    }
}
11.12.2008 12:50:04
4 ОТВЕТА
РЕШЕНИЕ

Я думаю, я понимаю, откуда ты. Вам просто нужно отойти от первоначальной точки привязки (щелчок левой кнопкой мыши), прежде чем привязаться к новой точке.

Вот 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

2
12.12.2008 01:49:38

Ваша мышь продолжает привязываться к той же точке, если вы пытаетесь переместить ее - потому что она все еще ближе к этой точке ... Если вы перемещаете мышь влево, переместите курсор в точку слева от текущей вместо пересчета в электрический ток. Подать заявку на 3 других направления ...

Я не рекомендовал бы такое поведение, хотя, это вызовет много раздражения. Привязывайте свои элементы управления к сетке, а не к мышке.

3
11.12.2008 13:00:23

Не изменяйте положение курсора. Вам не нужно.

Вместо этого нарисуйте, как будто он был привязан к сетке. Когда пользователь щелкает где-то, просто нарисуйте линию из ближайших точек сетки.

Например, если пользователь нажимает на (197,198), но вы знаете, что ближайшая точка на самом деле - (200,200), просто нарисуйте линию (200,200) вместо (197,198).

И, пожалуйста, не связывайтесь с реальной позицией курсора.


Я не знаю, есть ли способ скрыть курсор мыши. Если есть, вы можете скрыть это и нарисовать самостоятельно, не изменяя реальную позицию .

6
26.06.2009 01:54:30

Я согласен с ruijoel, не связывайтесь с позицией курсора. Лучше иметь крест или кольцо, которые нарисованы в точке привязки, чтобы показать пользователю, к какой точке будет привязана точка щелчка.

Чтобы это работало хорошо, вы можете захотеть взглянуть на xor-Drawing, чтобы элемент удалялся при переходе к новой точке привязки.

0
11.12.2008 15:09:56