Search code examples
c#classdrawpictureboxgeometry

How to control size and location of circle when I draw it


I need help with a problem that I don't know how to solve it. I have my own class that extends from PictureBox, I can show my rectangle correctly and I can move it without problems.

But when I try to draw a circle arround the rectangle, I have a problem. I want to draw the circle when the users make a mouseclickevent. It draws a circle, but on the rectangle. I don't know if you understand me... I put my code below and also the results that I have and the results that I want to have.

My code:

OnClick event:

//Métodos para mover la unidad
    bool unidadPulsada = false;
    private Point MouseDownLocation;
    protected override void OnMouseDown(MouseEventArgs e)
    {
        unidadPulsada = true;
        base.OnMouseDown(e);
        MouseDownLocation = e.Location;
        DibujarLimites();
    }

Method that set the pictureBox:

public void Colocar(Control control, Unidad unidad, Point p)
    {
        unidad.Location = p;
        control.Controls.Add(unidad);
    }

Methods that draw:

public void DibujarLimites()
    {
        using (Graphics g = CreateGraphics())
        {
            using (Pen pen = new Pen(Color.Red, 2))
            {
                float[] dashValues = { 5, 2, 15, 4 };
                pen.DashPattern = dashValues;
                DrawCircle(g, pen, 0, 0, 20);
            }
        }
    }

    public void DrawCircle(Graphics g, Pen pen, float centerX, float centerY, float radius)
    {
        g.DrawEllipse(pen, centerX - radius, centerY - radius,
                      radius + radius, radius + radius);
    }

The results I have: The left rectangle is the pictureBox with the circle draw on it. The right rectangle is the pictureBox without the circle, the original rectangle. enter image description here

The results I want to have: The circle drawed arround the rectangle.

enter image description here

EDIT for Youri:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Windows.Forms;
using WHF.Properties;

namespace WHF
{
public class Unidad : PictureBox
{
    //Constructor
    public Unidad(string nombre, string tipo, int movimiento, int ha, int hp, int fuerza, int resistencia, int heridas, int iniciativa, int ataques, int liderazgo, int coste, string rutaImagen)
    {
        tipoUnidad = tipo;
        movimientoUnidad = movimiento;
        nombreUnidad = nombre;
        costeUnidad = coste;
        haUnidad = ha;
        hpUnidad = hp;
        fuerzaUnidad = fuerza;
        resistenciaUnidad = resistencia;
        iniciativaUnidad = iniciativa;
        ataquesUnidad = ataques;
        liderazgoUnidad = liderazgo;
        rutaImagenUnidad = rutaImagen;
    }

    //Propiedades
    public string nombreUnidad { get; set; }
    public string tipoUnidad { get; set; }
    public int movimientoUnidad { get; set; }
    public int costeUnidad { get; set; }
    public int haUnidad { get; set; }
    public int hpUnidad { get; set; }
    public int fuerzaUnidad { get; set; }
    public int resistenciaUnidad { get; set; }
    public int heridasUnidad { get; set; }
    public int iniciativaUnidad { get; set; }
    public int ataquesUnidad { get; set; }
    public int liderazgoUnidad { get; set; }
    public string rutaImagenUnidad { get; set; }

    //Método para dibujar unidad
    public void Colocar(Control control, Unidad unidad, Point p)
    {
        unidad.Location = p;
        control.Controls.Add(unidad);
    }


    //Métodos para mover la unidad
    bool unidadPulsada = false;
    private Point MouseDownLocation;
    protected override void OnMouseDown(MouseEventArgs e)
    {
        unidadPulsada = true;
        base.OnMouseDown(e);
        MouseDownLocation = e.Location;
        //DibujarLimites();

        float x = Location.X + e.X;
        float y = Location.Y + e.Y;

        Graphics graphics = CreateGraphics();

        PointF center = new PointF(x, y);//this.ClientSize.Width / 2F, this.ClientSize.Height / 2F);
        float radius = 100;

        PointF rectOrigin = new PointF(center.X - radius, center.Y - radius);
        RectangleF r = new RectangleF(rectOrigin, new SizeF(radius * 2F, radius * 2F));

        using (Pen p = new Pen(Color.Red, 4))
        {
            p.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
            graphics.DrawEllipse(p, r);
        }
    }
    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);
        if (unidadPulsada)
        {
            Left = e.X + Left - MouseDownLocation.X;
            Top = e.Y + Top - MouseDownLocation.Y;
        }
    }
    protected override void OnMouseUp(MouseEventArgs e)
    {
        unidadPulsada = false;
        base.OnMouseDown(e);
        LimpiarLimites();
    }

    //Método para dibujar la zona límite de movimiento de la unidad
    public void DibujarLimites()
    {
        using (Graphics g = CreateGraphics())
        {
            using (Pen pen = new Pen(Color.Red, 2))
            {
                float[] dashValues = { 5, 2, 15, 4 };
                pen.DashPattern = dashValues;
                DrawCircle(g, pen, 0, 0, 20);
            }
        }
    }

    //Método para limpiar el dibujo de la zona límite
    public void LimpiarLimites()
    {

    }

    public void DrawCircle(Graphics g, Pen pen, float centerX, float centerY, float radius)
    {
        g.DrawEllipse(pen, centerX - radius, centerY - radius, radius + radius, radius + radius);
    }

    public void FillCircle(Graphics g, Brush brush, float centerX, float centerY, float radius)
    {
        g.FillEllipse(brush, centerX - radius, centerY - radius, radius + radius, radius + radius);
    }
}
}

Solution

  • Okay here is an example, I tried to apply the same way as you did, I have created my own picture box,

    class MyPBox : PictureBox
        {
        public MyPBox()
        {
            this.BackColor = Color.Red; // for see better
            this.Location = new Point(50, 50); // set location at form
    
        }
        protected override void OnPaint(PaintEventArgs pe)
        {
            if (this.Parent != null)
            {
                this.Parent.Paint += Parent_Paint; // picturebox's paint means it added to parent so we need to trigger parent's paint event
            }
            base.OnPaint(pe);
    
        }
        bool clickPerformed = false; // to catch control has mouse down
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            clickPerformed = true; // set mouse down
            Control tempSender =  this.Parent; // get sender
            tempSender.Invalidate(); // invalidate to trigger paint event
    
        }
    
        private void Parent_Paint(object sender, PaintEventArgs e)
        {
            if (clickPerformed)
            {
                using (Graphics g = e.Graphics)
                {
                    using (Pen pen = new Pen(Color.Black, 2))
                    {
                        float locationX = this.Location.X + this.Size.Width / 2;
                        float locationY = this.Location.Y + this.Size.Height / 2;
                        float radius = (this.Size.Height + this.Size.Width) / 2;
    
                        float[] dashValues = { 5, 2, 15, 4 };
                        pen.DashPattern = dashValues;
                        DrawCircle(g, pen, locationX
                            , locationY
                            , radius); // draw circle 
                        clickPerformed = false; // process done so set it to false
                    }
                }
            }
            base.OnPaint(e);
    
        }
    
        protected override void OnMouseUp(MouseEventArgs e)
        {
            this.Parent.Invalidate(); // mouse up circle should be erased, so invalidate again to trigger paint, but this time clickPerformed is false
            // so it won't draw circle again
            base.OnMouseDown(e);
        }
        public void DrawCircle(Graphics g, Pen pen, float centerX, float centerY, float radius)
        {
            g.DrawEllipse(pen, centerX - radius, centerY - radius, radius + radius, radius + radius);
        }
    
    }
    

    Result(I am clicking on picturebox btw :) );

    enter image description here

    Hope helps,