Saltar al contenido

Circular Picture Box – Border Gradient color + Styles – C# & WinForms

Hola, ahora crearemos un cuadro de imagen circular con un color degradado de borde, con varios tipos de estilo de línea, por ejemplo; solido, guiones, puntos, combinado entre guiones y punto, o simplemente sin borde. Tambien poder establecer el estilo de tapa al final o inicio de un guion, por ejemplo, un estilo plano, redondeado o triangular.

Hacerlo es muy sencillo, no tomará mucho tiempo 😉

1.- Crear clase

Primeramente agregar una nueva clase y colocar cualquier nombre, en mi caso pondré RJCircularPictureBox.

2.- Importar librería Windows.Form y Drawing

Para hacer cualquier control personalizado/extendido, es necesario importar la librería Windows Forms y la librería de dibujos (Drawing), opcionalmente, también importar la librería ComponentModel para implementar atributos en las propiedades del control.

using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.ComponentModel;

3.- Heredar la clase PictureBox

Heredar el control PictureBox, para así personalizar la apariencia y extender su funcionalidad.

    class RJCircularPictureBox : PictureBox
    {
    }

4.- Declarar campos

Una vez heredado la clase PictureBox, declarar campos para la apariencia y asignar sus valores predeterminados, en este caso: tamaño de borde, color de borde 1 y 2 para establecer un color degradado del borde, estilo de línea y tapa, finalmente un campo para el ángulo del degradado.

    //Fields
    private int borderSize = 2;
    private Color borderColor = Color.RoyalBlue;
    private Color borderColor2 = Color.HotPink;
    private DashStyle borderLineStyle = DashStyle.Solid;
    private DashCap borderCapStyle = DashCap.Flat;
    private float gradientAngle = 50F;

5.- Constructor

En el constructor, simplemente establecer un mismo tamaño para el alto y ancho. Y opcionalmente establecer el modo de tamaño, en este caso, indicaré que la imagen se ajuste al tamaño del cuadro de imagen.

    //Constructor
    public RJCircularPictureBox()
    {
        this.Size = new Size(100, 100);
        this.SizeMode = PictureBoxSizeMode.StretchImage;
    }

6.- Generar propiedades

Crear los descriptores de acceso de los campos definidos anteriormente, y así poder cambiar la apariencia del control desde el cuadro de propiedades. Una vez creado las propiedades, en los descriptores de acceso Set, invocar el método Invalidate(), para repintar el control y así actualizar la apariencia.

    //Properties
    [Category("RJ Code Advance")]
    public int BorderSize
    {
        get { return borderSize; }
        set
        {
            borderSize = value;
            this.Invalidate();
        }
    }

    [Category("RJ Code Advance")]
    public Color BorderColor
    {
        get { return borderColor; }
        set
        {
            borderColor = value;
            this.Invalidate();
        }
    }

    [Category("RJ Code Advance")]
    public Color BorderColor2
    {
        get { return borderColor2; }
        set
        {
            borderColor2 = value;
            this.Invalidate();
        }
    }

    [Category("RJ Code Advance")]
    public DashStyle BorderLineStyle
    {
        get { return borderLineStyle; }
        set
        {
            borderLineStyle = value;
            this.Invalidate();
        }
    }

    [Category("RJ Code Advance")]
    public DashCap BorderCapStyle
    {
        get { return borderCapStyle; }
        set
        {
            borderCapStyle = value;
            this.Invalidate();
        }
    }

    [Category("RJ Code Advance")]
    public float GradientAngle
    {
        get { return gradientAngle; }
        set
        {
            gradientAngle = value;
            this.Invalidate();
        }
    }

7.- Anular el evento OnResize

Es necesario anular el método de evento OnResize, para que el cuadro de imagen circular tenga siempre el mismo alto y ancho, es decir, un círculo perfecto.

    //Overridden methods
    protected override void OnResize(EventArgs e)
    {
        base.OnResize(e);
        this.Size = new Size(this.Width, this.Width);
    }

8.- Anular el evento OnPaint

Finalmente, anular el método de evento OnPaint para agregar o crear una apariencia personalizada.

    protected override void OnPaint(PaintEventArgs pe)
    {
        base.OnPaint(pe);
        //Fields
        var graph = pe.Graphics;
        var rectContourSmooth = Rectangle.Inflate(this.ClientRectangle, -1, -1);
        var rectBorder = Rectangle.Inflate(rectContourSmooth, -borderSize, -borderSize);
        var smoothSize = borderSize > 0 ? borderSize * 3 : 1;
        using (var borderGColor = new LinearGradientBrush(rectBorder, borderColor, borderColor2, gradientAngle))
        using (var pathRegion = new GraphicsPath())
        using (var penSmooth = new Pen(this.Parent.BackColor, smoothSize))
        using (var penBorder = new Pen(borderGColor, borderSize))
        {
            graph.SmoothingMode = SmoothingMode.AntiAlias;
            penBorder.DashStyle = borderLineStyle;
            penBorder.DashCap = borderCapStyle;
            pathRegion.AddEllipse(rectContourSmooth);
            //Set rounded region 
            this.Region = new Region(pathRegion);

            //Drawing
            graph.DrawEllipse(penSmooth, rectContourSmooth);//Draw contour smoothing
            if (borderSize > 0) //Draw border
                graph.DrawEllipse(penBorder, rectBorder);
        }
    }

Video tutorial