1 Pluspunkt 0 Minuspunkte

Ich will ein Element draggen können aber so das es immer auf dem nächstgelegenen raster einrastet.

using System;
using System.Drawing;
using System.Windows.Forms;

namespace GridWithDragDrop
{
    public class MainForm : Form
    {
        private const int gridSize = 50;
        private Point startPoint;
        private Point originalLocation;
        private bool isDragging;

        public MainForm()
        {
            this.Text = "Grid with Drag & Drop";
            this.Size = new Size(600, 400);
            this.DoubleBuffered = true;

            // Ereignisbehandlung für das Zeichnen des Rasters und das Verschieben der Elemente
            this.Paint += MainForm_Paint;
            this.MouseDown += MainForm_MouseDown;
            this.MouseMove += MainForm_MouseMove;
            this.MouseUp += MainForm_MouseUp;
        }

        private void MainForm_Paint(object sender, PaintEventArgs e)
        {
            // Raster zeichnen
            using (Pen gridPen = new Pen(Color.LightGray))
            {
                for (int x = 0; x < this.ClientSize.Width; x += gridSize)
                {
                    e.Graphics.DrawLine(gridPen, x, 0, x, this.ClientSize.Height);
                }
                for (int y = 0; y < this.ClientSize.Height; y += gridSize)
                {
                    e.Graphics.DrawLine(gridPen, 0, y, this.ClientSize.Width, y);
                }
            }
        }

        private void MainForm_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                startPoint = e.Location;
                originalLocation = startPoint;
                isDragging = true;
            }
        }

        private void MainForm_MouseMove(object sender, MouseEventArgs e)
        {
            if (isDragging)
            {
                Point newLocation = SnapToGrid(e.Location);
                this.Invalidate(); // Neuzeichnen erzwingen, um das alte Label zu löschen
                startPoint = newLocation;
            }
        }

        private void MainForm_MouseUp(object sender, MouseEventArgs e)
        {
            if (isDragging)
            {
                Point newLocation = SnapToGrid(e.Location);
                this.Invalidate(); // Neuzeichnen erzwingen, um das alte Label zu löschen
                isDragging = false;
            }
        }

        private Point SnapToGrid(Point point)
        {
            // Berechnen der nächsten Rasterposition
            int xSnap = (point.X + gridSize / 2) / gridSize * gridSize;
            int ySnap = (point.Y + gridSize / 2) / gridSize * gridSize;

            return new Point(xSnap, ySnap);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            if (isDragging)
            {
                // Zeichnen des Labels während des Ziehens
                using (Brush brush = new SolidBrush(Color.LightBlue))
                {
                    e.Graphics.FillRectangle(brush, startPoint.X, startPoint.Y, gridSize, gridSize);
                }
            }
            else
            {
                // Wenn das Ziehen abgeschlossen ist, fügen Sie das Label hinzu
                using (Brush brush = new SolidBrush(Color.LightBlue))
                {
                    Point snapPoint = SnapToGrid(originalLocation);
                    e.Graphics.FillRectangle(brush, snapPoint.X, snapPoint.Y, gridSize, gridSize);
                }
            }
        }

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
    }
}

Aber sobald ich das Element loslasse rutscht es wieder dorthin wo ich begonnen habe es zu ziehen und außerdem schnappt es manchmal auf dem benachbarten Feld ein.

von  

1 Antwort

0 Pluspunkte 0 Minuspunkte

Das Problem scheint in der Methode SnapToGrid zu liegen.

// Berechnen der nächsten Rasterposition
int xSnap = (point.X + gridSize / 2) / gridSize * gridSize;
int ySnap = (point.Y + gridSize / 2) / gridSize * gridSize;

Wenn du das gridsize / 2 weglässt

int xSnap = (point.X) / gridSize * gridSize;
int ySnap = (point.Y) / gridSize * gridSize;

dann sollte es genau auf dem darunterliegenden Feld einrasten. In der OnPaint Methode

// Wenn das Ziehen abgeschlossen ist, fügen Sie das Label hinzu
using (Brush brush = new SolidBrush(Color.LightBlue))
{
    Point snapPoint = SnapToGrid(originalLocation);
    e.Graphics.FillRectangle(brush, snapPoint.X, snapPoint.Y, gridSize, gridSize);
}

setzt du außerdem die neue Position auf die ursprüngliche Position was der Grund dafür ist das das Element auf seine ursprüngliche Position zurück rutscht. Hier ist ein überarbeitetes Beispiel.

using System;
using System.Drawing;
using System.Windows.Forms;

namespace GridWithDragDrop
{
    public class MainForm : Form
    {
        private const int gridSize = 50;
        private Point startPoint;
        private Point originalLocation;
        private bool isDragging;
        private Point newLocation;

        public MainForm()
        {
            this.Text = "Grid with Drag & Drop";
            this.Size = new Size(600, 400);
            this.DoubleBuffered = true;

            // Ereignisbehandlung für das Zeichnen des Rasters und das Verschieben der Elemente
            this.Paint += MainForm_Paint;
            this.MouseDown += MainForm_MouseDown;
            this.MouseMove += MainForm_MouseMove;
            this.MouseUp += MainForm_MouseUp;
        }

        private void MainForm_Paint(object sender, PaintEventArgs e)
        {
            // Raster zeichnen
            using (Pen gridPen = new Pen(Color.LightGray))
            {
                for (int x = 0; x < this.ClientSize.Width; x += gridSize)
                {
                    e.Graphics.DrawLine(gridPen, x, 0, x, this.ClientSize.Height);
                }
                for (int y = 0; y < this.ClientSize.Height; y += gridSize)
                {
                    e.Graphics.DrawLine(gridPen, 0, y, this.ClientSize.Width, y);
                }
            }
        }

        private void MainForm_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                startPoint = e.Location;
                originalLocation = startPoint;
                isDragging = true;
            }
        }

        private void MainForm_MouseMove(object sender, MouseEventArgs e)
        {
            if (isDragging)
            {
                newLocation = SnapToGrid(e.Location);
                this.Invalidate(); // Neuzeichnen erzwingen, um das alte Label zu löschen
                startPoint = newLocation;
            }
        }

        private void MainForm_MouseUp(object sender, MouseEventArgs e)
        {
            if (isDragging)
            {
                newLocation = SnapToGrid(e.Location);
                this.Invalidate(); // Neuzeichnen erzwingen, um das alte Label zu löschen
                isDragging = false;
            }
        }

        private Point SnapToGrid(Point point)
        {
            // Berechnen der nächsten Rasterposition
            int xSnap = (point.X ) / gridSize * gridSize;
            int ySnap = (point.Y ) / gridSize * gridSize;

            return new Point(xSnap, ySnap);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            if (isDragging)
            {
                // Zeichnen des Labels während des Ziehens
                using (Brush brush = new SolidBrush(Color.LightBlue))
                {
                    e.Graphics.FillRectangle(brush, startPoint.X, startPoint.Y, gridSize, gridSize);
                }
            }
            else
            {
                // Wenn das Ziehen abgeschlossen ist, fügen Sie das Label hinzu
                using (Brush brush = new SolidBrush(Color.LightBlue))
                {
                    Point snapPoint = SnapToGrid(newLocation);
                    e.Graphics.FillRectangle(brush, snapPoint.X, snapPoint.Y, gridSize, gridSize);
                }
            }
        }

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
    }
}
von (732 Punkte)