Extendiendo un ProgressBar. FlatProgressBar.

by Valeriano Tortola 6. octubre 2007 19:58
FlatProgressBar

Vamos con una de Arts Attack... El ProgressBar de .NET es "bonito", sobre todo en Windows Vista, pero a mi gusto prefería menos destellos fashion y un poco más de información... y ya puestos ... un estilo flat :D 

En vez de crear uno from scratch, mucho mejor extender el ProgressBar, añadirle nuevas propiedades y redefinir como repintarlo. Código fuente al final del artículo ;)

 

Entre los puntos fuertes de extender un control WinForm, esta el de redifinir los estilo con Control.SetStyle y sobreescribir el método OnPaint, dentro de este obtemenos el objeto Graphics con el que podemos pintar formas y textos. Mediante atributos configuramos los elementos que Visual Studio usará para mostrar sus propiedades:

  • ToolBoxBitmap: Sobre la clase, indica el icono  FlatProgressBar que mostrará Visual Studio en la paleta de componentes. Se añade una imagen .bmp al proyecto como recurso embebido, después se indica tal y como aparece en el código. A veces no funciona bien, así que hay un truco creando esa clase vacia 'resfinder' y luego indicando la imagen junto al Namespace, funciona siempre :D
  • Browsable: Sobre una propiedad, indica si Visual Studio debe mostrarla en el Property Grid.
  • CategoryAttribute: Sobre una propiedad, indica en que categoria del Property Grid colocarla.
  • DescriptionAttribute: Sobre una propiedad, indica la descripción de esa propiedad en el Property Grid.

flatprogressbartool Una vez generado el componente en un ensamblado, para usarlo solo tenemos que añadirlo a la paleta de nuestro VS2005, desde el ToolBox, botón derecho, Choose Items, le damos a Browse para ir hasta el ensamblado, lo selecionamos y se añade a la paleta.

Asi mediante VS2005 podemos configurar los nuevos elementos de nuestro ProgressBar, además de ocultar otros que no nos interesan como se puede ver con por ejemplo la propiedad Style.

 

  Pintar en un formulario es relativemente fácil con la clase Graphics y sus utilidades, pero requiere algo de paciencia y "prueba-error" para ajustarlo adecuadamente. Me apunto en el TODO escribir sobre las nociones básicas de GDI+.

Y ahora... el código fuente:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.ComponentModel;
 
internal class resfinder { }
 
namespace CustomProgressBars
{
  [ToolboxBitmap(typeof(resfinder), "FlatProgressBar.FlatProgressBar.bmp")]
  public class FlatProgressBar : ProgressBar
  {
    private Pen _border;
    private String _text;
    private SolidBrush _brushForeColor;
    private SolidBrush _brushBarColor;
 
    [Browsable(true)]
    [CategoryAttribute("FlatProgressBar"),
    DescriptionAttribute("Color de la Barra")]
    public Color BarColor
    {
      get { return _brushBarColor.Color; }
      set { _brushBarColor.Color = value; }
    }
 
    [Browsable(true)]
    [CategoryAttribute("FlatProgressBar"),
    DescriptionAttribute("Color del Texto")]
    public Color TextColor
    {
      get { return _brushForeColor.Color; }
      set { _brushForeColor.Color = value; }
    }
 
    [Browsable(true)]
    [CategoryAttribute("FlatProgressBar"),
    DescriptionAttribute("Color del Borde")]
    public Color BorderColor
    {
      get { return _border.Color; }
      set { _border.Color = value; }
    }
 
    [Browsable(true)]
    [CategoryAttribute("FlatProgressBar"),
    DescriptionAttribute("Color del Borde")]
    public Single BorderWidth
    {
      get { return _border.Width; }
      set { _border.Width = value; }
    }
 
    [Browsable(true)]
    [CategoryAttribute("FlatProgressBar"),
    DescriptionAttribute("Color de Fondo")]
    public new Color BackColor
    {
      get { return base.BackColor; }
      set { base.BackColor = value; }
    }
 
    [Browsable(true)]
    [CategoryAttribute("FlatProgressBar"),
    DescriptionAttribute("Texto de la barra"),
    DefaultValue("Text")]
    public new String Text
    {
      get { return _text; }
      set { _text = value; }
    }
 
    [Browsable(true)]
    [CategoryAttribute("FlatProgressBar"),
    DescriptionAttribute("Tipo de fuente del texto.")]
    public new Font Font
    {
      get { return base.Font; }
      set { base.Font = value; }
    }
 
    [Browsable(false)]
    new public ProgressBarStyle Style
    {
      get { return ProgressBarStyle.Continuous; }
      set { }
    }
 
    [Browsable(false)]
    new public Int32 MarqueeAnimationSpeed
    {
      get { return 0; }
      set { }
    }
 
    [Browsable(false)]
    new public Color ForeColor
    {
      get { return TextColor; }
      set { }
    }
 
    public FlatProgressBar()
    {
      InitializeComponent();
    }
 
    private void InitializeComponent()
    {
      this.SetStyle(ControlStyles.AllPaintingInWmPaint |
      ControlStyles.UserPaint |
      ControlStyles.OptimizedDoubleBuffer |
      ControlStyles.ResizeRedraw |
      ControlStyles.SupportsTransparentBackColor, true);
 
      _border = new Pen(Brushes.Black);
      _brushForeColor = new SolidBrush(Color.White);
      _brushBarColor = new SolidBrush(Color.Gray);
      base.Font = new Font("Tahoma", 10, FontStyle.Bold);
    }
 
    protected override void OnPaint(PaintEventArgs e)
    {
      // cuando mide cada paso
      Single step = (Single)this.Width / this.Maximum;
 
      // cuantos puntos es el progreso actual
      Single progressInPoints = (this.Value * step);
      progressInPoints = progressInPoints > 0 ? progressInPoints : 0;
 
      // barra de progreso
      e.Graphics.FillRectangle(_brushBarColor, 0, 0, progressInPoints, this.Height);
 
      // texto con antialias
      SmoothingMode bk = e.Graphics.SmoothingMode;
      e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
 
      // escribo el texto
      e.Graphics.DrawString(_text, Font, _brushForeColor,
                  new PointF(6, (this.Height - this.Font.Height) / 2));
 
      string percent = ((this.Maximum / 100) * this.Value).ToString() + '%';
      percent = percent.PadLeft(4, ' ');
 
      // mido el porcentaje en puntos para saber
      // donde ubicarlo 
      SizeF swidth = e.Graphics.MeasureString(percent, base.Font);
 
      // escribo porcentaje
      e.Graphics.DrawString(percent, base.Font, _brushForeColor,
                  new PointF((this.Width - _border.Width - swidth.Width - 1),
                             (this.Height - base.Font.Height) / 2));
 
      // restauro el modo
      e.Graphics.SmoothingMode = bk;
 
      // dibujo el border si es mayor que 0
      if (_border.Width >= 1)
        e.Graphics.DrawRectangle(_border, 0, 0, this.Width - 1, this.Height - 1);
    }
 
  }
}

Tags: ,

.NET 2.0 | C# 2.0 | WinApps

Comentarios

06/10/2007 20:04:54 #

trackback

Trackback from vtortola

Extendiendo un ProgressBar. FlatProgressBar.

vtortola |

Comentarios no permitidos