百分比控件----------WinForm控件开发系列

  /// <summary>
  /// 百分比控件
  /// </summary>
  [ToolboxItem(true)]
  [DefaultProperty("Value")]
  [DefaultEvent("ValueChanged")]
  [Description("百分比控件")]
  public partial class PercentageBarExt : Control
  {
    public delegate void ValueEventHandler(object sender, ValueEventArgs e);

    #region

    private event ValueEventHandler valueChanged;
    /// <summary>
    /// 百分比值更改事件
    /// </summary>
    [Description("百分比值更改事件")]
    public event ValueEventHandler ValueChanged
    {
      add { this.valueChanged += value; }
      remove { this.valueChanged -= value; }
    }

    private PercentageType type = PercentageType.Annulus;
    /// <summary>
    /// 百分比显示类型
    /// </summary>
    [DefaultValue(PercentageType.Annulus)]
    [Description("百分比显示类型")]
    public PercentageType Type
    {
      get { return this.type; }
      set
      {
        if (this.type == value)
          return;
        this.type = value;
        this.Invalidate();
      }
    }

    private int arcRadius = 50;
    /// <summary>
    /// 圆形半径
    /// </summary>
    [DefaultValue(50)]
    [Description("圆形半径")]
    public int ArcRadius
    {
      get { return this.arcRadius; }
      set
      {
        if (this.arcRadius == value || value < 0)
          return;
        this.arcRadius = value;
        this.Invalidate();
      }
    }

    private int arcAngle = 360;
    /// <summary>
    /// 圆弧弧度大小
    /// </summary>
    [DefaultValue(360)]
    [Description("圆弧弧度大小")]
    public int ArcAngle
    {
      get { return this.arcAngle; }
      set
      {
        if (this.arcAngle == value || value < 0 || value > 360)
          return;
        this.arcAngle = value;
        this.Invalidate();
      }
    }

    private int arcThickness = 10;
    /// <summary>
    /// 弧线大小
    /// </summary>
    [DefaultValue(10)]
    [Description("弧线大小")]
    public int ArcThickness
    {
      get { return this.arcThickness; }
      set
      {
        if (this.arcThickness == value || value < 0 || value > this.ArcRadius)
          return;
        this.arcThickness = value;
        this.Invalidate();
      }
    }

    private bool arcRound = false;
    /// <summary>
    /// 弧线是否为圆角
    /// </summary>
    [DefaultValue(false)]
    [Description("弧线是否为圆角")]
    public bool ArcRound
    {
      get { return this.arcRound; }
      set
      {
        if (this.arcRound == value)
          return;
        this.arcRound = value;
        this.Invalidate();
      }
    }

    private Color arcAnnulusBackColor = Color.Empty;
    /// <summary>
    /// 环形背景颜色(仅限于Annulus、Sector)
    /// </summary>
    [DefaultValue(typeof(Color), "Empty")]
    [Description("环形背景颜色(仅限于Annulus、Sector)")]
    [Editor(typeof(ColorEditorExt), typeof(System.Drawing.Design.UITypeEditor))]
    public Color ArcAnnulusBackColor
    {
      get { return this.arcAnnulusBackColor; }
      set
      {
        if (this.arcAnnulusBackColor == value)
          return;
        this.arcAnnulusBackColor = value;
        this.Invalidate();
      }
    }

    private Color arcBackColor = Color.FromArgb(112, 220, 220, 220);
    /// <summary>
    /// 弧线背景颜色
    /// </summary>
    [DefaultValue(typeof(Color), "112, 220, 220, 220")]
    [Description("弧线背景颜色")]
    [Editor(typeof(ColorEditorExt), typeof(System.Drawing.Design.UITypeEditor))]
    public Color ArcBackColor
    {
      get { return this.arcBackColor; }
      set
      {
        if (this.arcBackColor == value)
          return;
        this.arcBackColor = value;
        this.Invalidate();
      }
    }

    private Color arcColor = Color.FromArgb(227, 240, 128, 128);
    /// <summary>
    /// 弧线颜色
    /// </summary>
    [DefaultValue(typeof(Color), "227, 240, 128, 128")]
    [Description("弧线颜色")]
    [Editor(typeof(ColorEditorExt), typeof(System.Drawing.Design.UITypeEditor))]
    public Color ArcColor
    {
      get { return this.arcColor; }
      set
      {
        if (this.arcColor == value)
          return;
        this.arcColor = value;
        this.Invalidate();
      }
    }

    #region 方形

    private int squareWidth = 10;
    /// <summary>
    /// 方形小格大小
    /// </summary>
    [DefaultValue(10)]
    [Description("方形小格大小")]
    public int SquareWidth
    {
      get { return this.squareWidth; }
      set
      {
        if (this.squareWidth == value || value < 0)
          return;
        this.squareWidth = value;
        this.Invalidate();
      }
    }

    private Color squareBorderColor = Color.FromArgb(149, 255, 255, 255);
    /// <summary>
    /// 方形小格边框颜色
    /// </summary>
    [DefaultValue(typeof(Color), "149, 255, 255, 255")]
    [Description("方形小格边框颜色")]
    [Editor(typeof(ColorEditorExt), typeof(System.Drawing.Design.UITypeEditor))]
    public Color SquareBorderColor
    {
      get { return this.squareBorderColor; }
      set
      {
        if (this.squareBorderColor == value)
          return;
        this.squareBorderColor = value;
        this.Invalidate();
      }
    }

    #endregion

    private float value = 0f;
    /// <summary>
    /// 百分比值
    /// </summary>
    [DefaultValue(0f)]
    [Description("百分比值")]
    public float Value
    {
      get { return this.value; }
      set
      {
        if (this.value == value || value < 0 || value > 1)
          return;
        this.value = value;
        if (this.valueChanged != null)
        {
          this.valueChanged(this, new ValueEventArgs() { Value = value });
        }
        this.Invalidate();
      }
    }

    private Font valueFont = new Font("宋体", 15);
    /// <summary>
    /// 百分比值字体
    /// </summary>
    [DefaultValue(typeof(Font), "宋体, 15pt")]
    [Description("百分比值字体")]
    public Font ValueFont
    {
      get { return this.valueFont; }
      set
      {
        if (this.valueFont == value)
          return;
        this.valueFont = value;
        this.Invalidate();
      }
    }

    private Color valueColor = Color.FromArgb(227, 255, 255, 255);
    /// <summary>
    /// 百分比值颜色
    /// </summary>
    [DefaultValue(typeof(Color), "227, 255, 255, 255")]
    [Description("百分比值颜色")]
    [Editor(typeof(ColorEditorExt), typeof(System.Drawing.Design.UITypeEditor))]
    public Color ValueColor
    {
      get { return this.valueColor; }
      set
      {
        if (this.valueColor == value)
          return;
        this.valueColor = value;
        this.Invalidate();
      }
    }

    protected override Size DefaultSize
    {
      get
      {
        return new Size(100, 100);
      }
    }

    #endregion

    public PercentageBarExt()
    {
      SetStyle(ControlStyles.UserPaint, true);
      SetStyle(ControlStyles.AllPaintingInWmPaint, true);
      SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
      SetStyle(ControlStyles.ResizeRedraw, true);
      SetStyle(ControlStyles.SupportsTransparentBackColor, true);

      InitializeComponent();
    }

    protected override void OnPaint(PaintEventArgs e)
    {
      base.OnPaint(e);

      Graphics g = e.Graphics;
      g.SmoothingMode = SmoothingMode.AntiAlias;
      Rectangle bounds_rect = new Rectangle((int)g.ClipBounds.X + ((int)g.ClipBounds.Width / 2 - this.ArcRadius) + 1, (int)g.ClipBounds.Y + ((int)g.ClipBounds.Height / 2 - this.ArcRadius) + 1, this.ArcRadius * 2 - 2, this.ArcRadius * 2 - 2);

      #region 环形
      if (this.Type == PercentageType.Annulus)
      {
        #region 背景
        Pen arcback_pen = new Pen(this.ArcBackColor, this.ArcThickness);
        g.DrawArc(arcback_pen, TransformRectangleF(bounds_rect, this.ArcThickness), 270, 360);
        arcback_pen.Dispose();
        #endregion

        if (this.ArcAnnulusBackColor != Color.Empty)
        {
          SolidBrush arcannulusback_sb = new SolidBrush(this.ArcAnnulusBackColor);
          g.FillPie(arcannulusback_sb, bounds_rect.X + this.ArcThickness / 2, bounds_rect.Y + this.ArcThickness / 2, bounds_rect.Width - this.ArcThickness, bounds_rect.Height - this.ArcThickness, 270, 360);
          arcannulusback_sb.Dispose();
        }

        #region 百分比值
        Pen arc_pen = new Pen(this.ArcColor, this.ArcThickness);
        if (this.ArcRound)
        {
          arc_pen.StartCap = LineCap.Round;
          arc_pen.EndCap = LineCap.Round;
        }
        g.DrawArc(arc_pen, TransformRectangleF(bounds_rect, this.ArcThickness), 270, 360 * this.Value);
        arc_pen.Dispose();
        #endregion

        #region 文本
        this.DrawValueText(g, bounds_rect);
        #endregion

      }
      #endregion
      #region 扇形
      else if (this.Type == PercentageType.Sector)
      {
        #region 背景
        SolidBrush arcback_sb = new SolidBrush(this.ArcBackColor);
        g.FillPie(arcback_sb, bounds_rect.X, bounds_rect.Y, bounds_rect.Width, bounds_rect.Height, 270, 360);
        arcback_sb.Dispose();
        #endregion

        if (this.ArcAnnulusBackColor != Color.Empty)
        {
          SolidBrush arcannulusback_sb = new SolidBrush(this.ArcAnnulusBackColor);
          g.FillPie(arcannulusback_sb, bounds_rect.X + this.ArcThickness / 2, bounds_rect.Y + this.ArcThickness / 2, bounds_rect.Width - this.ArcThickness, bounds_rect.Height - this.ArcThickness, 270, 360);
          arcannulusback_sb.Dispose();
        }

        #region 百分比值
        SolidBrush arc_sb = new SolidBrush(this.ArcColor);
        g.FillPie(arc_sb, bounds_rect.X, bounds_rect.Y, bounds_rect.Width, bounds_rect.Height, 270, 360 * this.Value);
        arc_sb.Dispose();
        #endregion

        #region 文本
        this.DrawValueText(g, bounds_rect);
        #endregion

      }
      #endregion
      #region 圆弧
      else if (this.Type == PercentageType.Arc)
      {
        int start = this.ArcAngle == 360 ? 270 : 180 + (180 - this.ArcAngle) / 2;

        #region 背景
        Pen arcback_pen = new Pen(this.ArcBackColor, this.ArcThickness);
        g.DrawArc(arcback_pen, TransformRectangleF(bounds_rect, this.ArcThickness), start, this.ArcAngle);
        arcback_pen.Dispose();
        #endregion

        #region 百分比值
        Pen arc_pen = new Pen(this.ArcColor, this.ArcThickness);
        if (this.ArcRound)
        {
          arc_pen.EndCap = LineCap.Round;
        }
        g.DrawArc(arc_pen, TransformRectangleF(bounds_rect, this.ArcThickness), start, this.ArcAngle * this.Value);
        arc_pen.Dispose();
        #endregion

        #region 文本
        this.DrawValueText(g, bounds_rect);
        #endregion

      }
      #endregion
      #region 方形
      else if (this.Type == PercentageType.Square)
      {
        RectangleF rectf = new RectangleF();
        rectf.Width = 11 + this.SquareWidth * 10;
        rectf.Height = 11 + this.SquareWidth * 10;
        rectf.X = g.ClipBounds.X + (g.ClipBounds.Width - rectf.Width) / 2;
        rectf.Y = g.ClipBounds.Bottom - rectf.Height;

        #region 背景
        SolidBrush arcback_sb = new SolidBrush(this.ArcBackColor);
        g.FillRectangle(arcback_sb, rectf);
        arcback_sb.Dispose();
        #endregion

        #region 百分比值
        SolidBrush arc_sb = new SolidBrush(this.ArcColor);
        string str = this.Value.ToString("F4");
        int index = str.IndexOf('.');
        int row = int.Parse(str.Substring(index + 1, 1));
        RectangleF row_rectf = new RectangleF();
        row_rectf.Width = rectf.Width;
        row_rectf.Height = row * 1 + row * this.SquareWidth;
        row_rectf.X = rectf.X;
        row_rectf.Y = rectf.Bottom - row_rectf.Height;
        g.FillRectangle(arc_sb, row_rectf);

        int col = int.Parse(str.Substring(index + 2, 1));
        if (col > 0)
        {
          RectangleF col_rectf = new RectangleF();
          col_rectf.Width = col * 1 + col * this.SquareWidth;
          col_rectf.Height = this.SquareWidth + 1;
          col_rectf.X = rectf.X;
          col_rectf.Y = row_rectf.Y - col_rectf.Height;
          g.FillRectangle(arc_sb, col_rectf);
        }

        arc_sb.Dispose();
        #endregion

        #region 边框
        Pen arcbackborder_pen = new Pen(this.SquareBorderColor, 1);
        for (int i = 0; i < 11; i++)//
        {
          g.DrawLine(arcbackborder_pen, rectf.X, rectf.Y + i * 1 + i * this.SquareWidth, rectf.Right, rectf.Y + i * 1 + i * this.SquareWidth);
        }
        for (int i = 0; i < 11; i++)//
        {
          g.DrawLine(arcbackborder_pen, rectf.X + i * 1 + i * this.SquareWidth, rectf.Y, rectf.X + i * 1 + i * this.SquareWidth, rectf.Bottom);
        }
        arcbackborder_pen.Dispose();
        #endregion

        #region 百分比值文本
        string value_str = (this.Value * 100).ToString("F0") + "%";
        StringFormat value_sf = new StringFormat();
        value_sf.FormatFlags = StringFormatFlags.NoWrap;
        value_sf.Alignment = StringAlignment.Center;
        value_sf.Trimming = StringTrimming.None;
        Size value_size = g.MeasureString(value_str, this.ValueFont, new Size(), value_sf).ToSize();
        SolidBrush value_sb = new SolidBrush(this.ValueColor);
        g.DrawString(value_str, this.ValueFont, value_sb, new RectangleF(rectf.X + (rectf.Width - value_size.Width) / 2, rectf.Y - value_size.Height, value_size.Width, value_size.Height), value_sf);
        value_sb.Dispose();
        value_sf.Dispose();
        #endregion

      }
      #endregion
      #region 条形
      else if (this.Type == PercentageType.Bar)
      {
        RectangleF rectf = new RectangleF();
        rectf.Width = g.ClipBounds.Width - (this.ArcRound ? this.ArcThickness : 0);
        rectf.Height = this.ArcThickness;
        rectf.X = g.ClipBounds.X + (this.ArcRound ? this.ArcThickness / 2 : 0);
        rectf.Y = g.ClipBounds.Bottom - rectf.Height;

        #region 背景
        Pen arcback_pen = new Pen(this.ArcBackColor, this.ArcThickness);
        if (this.ArcRound)
        {
          arcback_pen.StartCap = LineCap.Round;
          arcback_pen.EndCap = LineCap.Round;
        }
        g.DrawLine(arcback_pen, rectf.X, rectf.Bottom - rectf.Height / 2, rectf.Right, rectf.Bottom - rectf.Height / 2);
        arcback_pen.Dispose();
        #endregion

        #region 百分比值
        Pen arc_pen = new Pen(this.ArcColor, this.ArcThickness);
        if (this.ArcRound)
        {
          arc_pen.StartCap = LineCap.Round;
          arc_pen.EndCap = LineCap.Round;
        }
        g.DrawLine(arc_pen, rectf.X, rectf.Bottom - rectf.Height / 2, (int)(rectf.Right * this.Value), rectf.Bottom - rectf.Height / 2);
        arc_pen.Dispose();
        #endregion

        #region 百分比值文本
        string value_str = (this.Value * 100).ToString("F0") + "%";
        StringFormat value_sf = new StringFormat();
        value_sf.FormatFlags = StringFormatFlags.NoWrap;
        value_sf.Alignment = StringAlignment.Center;
        value_sf.Trimming = StringTrimming.None;
        Size value_size = g.MeasureString(value_str, this.ValueFont, new Size(), value_sf).ToSize();
        SolidBrush value_sb = new SolidBrush(this.ValueColor);
        g.DrawString(value_str, this.ValueFont, value_sb, new RectangleF(rectf.X + (rectf.Width - value_size.Width) / 2, rectf.Y - value_size.Height, value_size.Width, value_size.Height), value_sf);
        value_sb.Dispose();
        value_sf.Dispose();
        #endregion

      }
      #endregion

    }

    /// <summary>
    /// 绘制百分值文本
    /// </summary>
    /// <param name="g"></param>
    /// <param name="rect"></param>
    private void DrawValueText(Graphics g, RectangleF rectf)
    {
      string value_str = (this.Value * 100).ToString("F0") + "%";
      StringFormat value_sf = new StringFormat();
      value_sf.FormatFlags = StringFormatFlags.NoWrap;
      value_sf.Alignment = StringAlignment.Center;
      value_sf.Trimming = StringTrimming.None;
      Size value_size = g.MeasureString(value_str, this.ValueFont, new Size(), value_sf).ToSize();
      SolidBrush value_sb = new SolidBrush(this.ValueColor);
      g.DrawString(value_str, this.ValueFont, value_sb, new RectangleF(rectf.X + (rectf.Width - value_size.Width) / 2, rectf.Y + (rectf.Height - value_size.Height) / 2, value_size.Width, value_size.Height), value_sf);
      value_sb.Dispose();
      value_sf.Dispose();
    }

    /// <summary>
    /// 根据画笔大小转换rectf
    /// </summary>
    /// <param name="rectf">要转换的rectf</param>
    /// <param name="pen">画笔大小大小</param>
    /// <returns></returns>
    private static RectangleF TransformRectangleF(RectangleF rectf, int pen)
    {
      RectangleF result = new RectangleF();
      result.Width = rectf.Width - (pen < 1 ? 0 : pen);
      result.Height = rectf.Height - (pen < 1 ? 0 : pen);
      result.X = rectf.X + (float)(pen / 2);
      result.Y = rectf.Y + (float)(pen / 2);
      return result;
    }

    protected override void Dispose(bool disposing)
    {
      if (disposing && (components != null))
      {
        components.Dispose();
      }
      base.Dispose(disposing);
    }

    /// <summary>
    /// 百分比值更改事件参数
    /// </summary>
    [Description("百分比值更改事件参数")]
    public class ValueEventArgs : EventArgs
    {
      /// <summary>
      /// 百分比值
      /// </summary>
      [Description("百分比值")]
      public float Value { get; set; }
    }

    /// <summary>
    /// 百分比显示类型
    /// </summary>
    [Description("百分比显示类型")]
    public enum PercentageType
    {
      /// <summary>
      /// 环形
      /// </summary>
      Annulus,
      /// <summary>
      /// 圆弧
      /// </summary>
      Arc,
      /// <summary>
      /// 扇形
      /// </summary>
      Sector,
      /// <summary>
      /// 方形
      /// </summary>
      Square,
      /// <summary>
      ///  条形
      /// </summary>
      Bar
    }

  }

源码下载:百分比控件.zip

猜你喜欢

转载自www.cnblogs.com/tlmbem/p/11427476.html
今日推荐