c# .net winforms gdi+ picturebox

c# - ¿Cómo puedo tratar el círculo como un control después de dibujarlo?-Mover y seleccionar formas



.net winforms (1)

Debe realizar una prueba de impacto para verificar si un punto está en un círculo. Como opción, puede agregar un círculo a GraphicsPath y usar el método IsVisible de la ruta para verificar si el punto está en círculo.

Por ejemplo, teniendo un punto p como ubicación superior izquierda de un círculo con diámetro d , puede verificar si el punto de clic actual está en el círculo o con esta:

var result = false; using (var path = new GraphicsPath()) { path.AddEllipse(p.X, p.Y, d, d); result = path.IsVisible(e.Location); }

Código de muestra

Veo que has hecho múltiples preguntas en este tema. Así que aquí comparto un código para ayudarlo a estar en la dirección correcta.

defina variables para el color de relleno, el color de relleno seleccionado, el tamaño del círculo, el ancho del borde, etc., para poder cambiarlos simplemente si lo necesita.

List<Rectangle> Shapes = new List<Rectangle>(); int selectedIndex = -1; Size size = new Size(25, 25); Color fillColor = Color.White; Color selectedfillCOlor = Color.Red; Color borderColor = Color.Gray; int borderWidth = 2;

Haga doble clic

Aquí agregue círculos a la lista de Shapes . Es suficiente agregar el rectángulo delimitador de un círculo a la lista.

private void pic_MouseDoubleClick(object sender, MouseEventArgs e) { var p = e.Location; p.Offset(-size.Width / 2, -size.Height / 2); Shapes.Add(new Rectangle(p, size)); pic.Invalidate(); }

Hacer clic

Aquí realice una prueba de golpe para verificar si el punto está en uno de los círculos. Verifique si la tecla Ctrl está presionada al hacer clic, para hacer la selección, luego configure el índice encontrado como selectedIndex para usarlo al pintar.

private void pic_MouseClick(object sender, MouseEventArgs e) { if (ModifierKeys != Keys.Control) return; selectedIndex = -1; for (int i = 0; i < Shapes.Count; i++) { using (var path = new GraphicsPath()) { path.AddEllipse(Shapes[i]); if (path.IsVisible(e.Location)) selectedIndex = i; } } pic.Invalidate(); }

Pintar

Establezca SmoothingMode del objeto gráfico en AntiAlias para tener un dibujo más suave. Luego dibuje formas en un bucle for y preste atención a selectedIndex para usar un color de relleno diferente para la forma seleccionada.

Para dibujar el texto, no necesita usar una label y simplemente puede dibujar texto usando la clase TextRenderer .

private void pic_Paint(object sender, PaintEventArgs e) { e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; for (int i = 0; i < Shapes.Count; i++) { var selected = (selectedIndex == i); using (var brush = new SolidBrush(selected ? selectedfillCOlor : fillColor)) e.Graphics.FillEllipse(brush, Shapes[i]); using (var pen = new Pen(borderColor, borderWidth)) e.Graphics.DrawEllipse(pen, Shapes[i]); TextRenderer.DrawText(e.Graphics, (i + 1).ToString(), this.Font, Shapes[i], Color.Black, TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter); } }

Algunas notas

  • Es mejor encapsular códigos en un nuevo control derivado de PictureBox o Control derivado y establecer DoubleBuffered en true.

  • Es una buena opción encapsular Circle en una clase Circle que realiza pruebas de impacto y renderiza un círculo. Especialmente si desea moverlos más tarde o realizar otras interacciones o dejar que cada círculo tenga sus propias propiedades como el color, etc.

Clase de muestra de círculo

Aquí hay una clase de círculo de muestra que puede ser un buen punto de partida.

public class Circle { private Color selectedFillColor = Color.Red; private Color normalFillColor = Color.Red; private Color borderColor = Color.Red; private int borderWidth = 2; public Point Location { get; set; } public int Diameter { get; set; } public Rectangle Bounds { get { return new Rectangle(Location, new Size(Diameter, Diameter)); } } public bool HitTest(Point p) { var result = false; using (var path = new GraphicsPath()) { path.AddEllipse(Bounds); result = path.IsVisible(p); } return result; } public bool Selected { get; set; } public void Draw(Graphics g) { using (var brush = new SolidBrush( Selected ? selectedFillColor : normalFillColor)) g.FillEllipse(brush, Bounds); using (var pen = new Pen(borderColor, 2)) g.DrawEllipse(pen, Bounds); } }

En realidad, después de hacer clic en cada círculo, quiero que se cambie su color, por ejemplo, quiero que se vuelva rojo. En general, quiero tratarlo como control.

Sé cómo dibujar los círculos que representan los nodos del gráfico cuando hago doble clic en el cuadro de imagen. Estoy usando el siguiente código:

public Form1() { InitializeComponent(); pictureBox1.Paint += new PaintEventHandler(pic_Paint); } public Point positionCursor { get; set; } private List<Point> points = new List<Point>(); public int circleNumber { get; set; } private void pictureBox1_DoubleClick(object sender, EventArgs e) { positionCursor = this.PointToClient(new Point(Cursor.Position.X - 25, Cursor.Position.Y - 25)); points.Add(positionCursor); Label lbl = new Label(); lbl.BackColor = Color.Transparent; lbl.Font = new Font("Arial", 7); lbl.Size = new Size(20, 15); if (circleNumber >= 10) { lbl.Location = new Point(points[circleNumber].X + 3, points[circleNumber].Y + 6); } else { lbl.Location = new Point(points[circleNumber].X + 7, points[circleNumber].Y + 7); } lbl.Text = circleNumber.ToString(); pictureBox1.Controls.Add(lbl); circleNumber++; pictureBox1.Invalidate(); } private void pic_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.SmoothingMode = SmoothingMode.AntiAlias; using (var pen = new Pen(Color.DimGray, 2)) { foreach (Point pt in points) { g.FillEllipse(Brushes.White, pt.X, pt.Y, 25, 25); g.DrawEllipse(pen, pt.X, pt.Y, 26, 26); } } }