visual objeto mover imagen como codeproject c# winforms user-interface drawing gdi+

objeto - Cómo arrastrar y mover formas en C#



gdi+ c# (1)

En una aplicación C # WindoeFormsAplicación, ¿es posible seleccionar, por lo tanto, mover o eliminar una forma trazada con el mouse? Al igual que el programa de pintura de Windows.

El trazado de formas funciona totalmente bien, todos los puntos se almacenan en alguna matriz. Como este ejemplo de dibujo lineal

Point Latest { get; set; } List<Point> _points = new List<Point>(); protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); // Save the mouse coordinates Latest = new Point(e.X, e.Y); // Force to invalidate the form client area and immediately redraw itself. Refresh(); } protected override void OnPaint(PaintEventArgs e) { var g = e.Graphics; base.OnPaint(e); if (_points.Count > 0) { var pen = new Pen(Color.Navy); var pt = _points[0]; for(var i=1; _points.Count > i; i++) { var next = _points[i]; g.DrawLine(pen, pt, next); pt = next; } g.DrawLine(pen, pt, Latest); } } private void Form1_MouseClick(object sender, MouseEventArgs e) { Latest = new Point(e.X, e.Y); _points.Add(Latest); Refresh(); }

Puedo dejar que calcule la distancia más corta entre la posición del mouse y cada línea mediante álgebra lineal básica, y establecer una distancia umbral, si es más corta que el umbral, seleccione esta línea y puede arrastrarla o editarla con el mouse. Pero, preguntándome, ¿hay alguna forma más manejable para tal tarea? Principalmente la parte de selección. Cualquier sugerencia será apreciada, gracias!


Para golpear formas de prueba no necesita álgebra lineal. Puede crear GraphicsPath para sus formas y luego usar el método GraphicsPath.IsOutlineVisible o GraphicsPath.IsOutlineVisible para realizar pruebas de impacto.

  • Para verificar si un punto está en el área de su camino, por ejemplo, una forma rellena, use IsVisible .

  • Para probar las líneas, curvas o formas vacías, puede usar IsOutlineVisible .

Ejemplo

Como ejemplo, puede crear una interfaz básica de IShape que contenga métodos para probar, dibujar y mover. Luego, en las clases, implemente esos métodos. También puede crear un control DrawingSurface que puede manejar pruebas de impacto, dibujar y mover objetos IShape .

En el siguiente ejemplo, creamos la interfaz IShape , clases de Line y Circle . También creamos un control DrawingSurface . Para probar el ejemplo, es suficiente poner un control DrawingSurface en un Form y manejar Load evento de formulario y agregar algunas formas, luego ejecutar la aplicación e intentar mover formas.

IShape

Esta interfaz contiene algunos métodos útiles que, si alguna clase los implementa, se pueden usar para dibujar, probar y mover. Al final de este ejemplo, puede ver un control IShape que puede funcionar con implementaciones de IShape simplemente:

public interface IShape { GraphicsPath GetPath(); bool HitTest(Point p); void Draw(Graphics g); void Move(Point d); }

Línea

Aquí hay una clase de línea que implementa la interfaz IShape . Cuando se realiza una prueba de impacto si hace clic en la línea, HitTest devuelve verdadero. Además, para permitirle elegir la línea de manera más simple, agregué 2 puntos para las pruebas de impacto:

public class Line : IShape { public Line() { LineWidth = 2; LineColor = Color.Black; } public int LineWidth { get; set; } public Color LineColor { get; set; } public Point Point1 { get; set; } public Point Point2 { get; set; } public GraphicsPath GetPath() { var path = new GraphicsPath(); path.AddLine(Point1, Point2); return path; } public bool HitTest(Point p) { var result = false; using (var path = GetPath()) using (var pen = new Pen(LineColor, LineWidth + 2)) result = path.IsOutlineVisible(p, pen); return result; } public void Draw(Graphics g) { using (var path = GetPath()) using (var pen = new Pen(LineColor, LineWidth)) g.DrawPath(pen, path); } public void Move(Point d) { Point1 = new Point(Point1.X + d.X, Point1.Y + d.Y); Point2 = new Point(Point2.X + d.X, Point2.Y + d.Y); } }

Circulo

Aquí hay una clase de círculo que implementa la interfaz IShape . Al hacer una prueba de golpe si hace clic en círculo, el HitTest devuelve verdadero:

public class Circle : IShape { public Circle() { FillColor = Color.Black; } public Color FillColor { get; set; } public Point Center { get; set; } public int Radious { get; set; } public GraphicsPath GetPath() { var path = new GraphicsPath(); var p = Center; p.Offset(-Radious, -Radious); path.AddEllipse(p.X, p.Y, 2 * Radious, 2 * Radious); return path; } public bool HitTest(Point p) { var result = false; using (var path = GetPath()) result = path.IsVisible(p); return result; } public void Draw(Graphics g) { using (var path = GetPath()) using (var brush = new SolidBrush(FillColor)) g.FillPath(brush, path); } public void Move(Point d) { Center = new Point(Center.X + d.X, Center.Y + d.Y); } }

DibujoSuperficie

El control, dibuja una lista de formas. También realiza pruebas de impacto en MouseDown y mueve la forma si la arrastra. Debería agregar algunas formas como la colección Line o Circle to Shapes del control.

public class DrawingSurface : Control { public List<IShape> Shapes { get; private set; } IShape selectedShape; bool moving; Point previousPoint = Point.Empty; public DrawingSurface() { DoubleBuffered = true; Shapes = new List<IShape>(); } protected override void OnMouseDown(MouseEventArgs e) { for (var i = Shapes.Count - 1; i >= 0; i--) if (Shapes[i].HitTest(e.Location)) { selectedShape = Shapes[i]; break; } if (selectedShape != null) { moving = true; previousPoint = e.Location; } base.OnMouseDown(e); } protected override void OnMouseMove(MouseEventArgs e) { if (moving) { var d = new Point(e.X - previousPoint.X, e.Y - previousPoint.Y); selectedShape.Move(d); previousPoint = e.Location; this.Invalidate(); } base.OnMouseMove(e); } protected override void OnMouseUp(MouseEventArgs e) { if (moving) { selectedShape = null; moving = false; } base.OnMouseUp(e); } protected override void OnPaint(PaintEventArgs e) { e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; foreach (var shape in Shapes) shape.Draw(e.Graphics); } }