水波纹进度控件----------WinForm控件开发系列

Posted tlmbem

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了水波纹进度控件----------WinForm控件开发系列相关的知识,希望对你有一定的参考价值。

技术图片

  /// <summary>
  /// 水波纹进度控件
  /// </summary>
  [ToolboxItem(true)]
  [DefaultProperty("Value")]
  [DefaultEvent("ValueChanged")]
  [Description("水波纹进度控件")]
  public partial class WaveProgressExt : 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 WaveProgressType type = WaveProgressType.Circle;
    /// <summary>
    /// 外观类型
    /// </summary>
    [DefaultValue(WaveProgressType.Circle)]
    [Description("外观类型")]
    public WaveProgressType Type
    
      get  return this.type; 
      set
      
        if (this.type == value)
          return;
        this.type = value;
        this.Invalidate();
      
    

    private bool active = false;
    /// <summary>
    /// 动画状态
    /// </summary>
    [DefaultValue(false)]
    [Description("动画状态")]
    public bool Active
    
      get  return this.active; 
      set
      
        if (this.active == value)
          return;
        this.active = value;
        this.waveTimer.Enabled = value;
      
    

    private bool borderShow = true;
    /// <summary>
    /// 是否显示边框
    /// </summary>
    [DefaultValue(true)]
    [Description("是否显示边框")]
    public bool BorderShow
    
      get  return this.borderShow; 
      set
      
        if (this.borderShow == value)
          return;
        this.borderShow = value;
        this.Invalidate();
      
    

    #region 水波纹

    private int waveInterval = 5;
    /// <summary>
    /// 水波纹移动速度
    /// </summary>
    [DefaultValue(5)]
    [Description("水波纹移动速度")]
    public int WaveInterval
    
      get  return this.waveInterval; 
      set
      
        if (this.waveInterval == value || value < 0)
          return;
        this.waveInterval = value;
      
    

    private float waveTension = 0.5f;
    /// <summary>
    /// 水波纹曲线的张力(0-1)
    /// </summary>
    [DefaultValue(0.5f)]
    [Description("水波纹曲线的张力(0-1)")]
    public float WaveTension
    
      get  return this.waveTension; 
      set
      
        if (this.waveTension == value || value < 0 || value > 1)
          return;
        this.waveTension = value;
        this.InitializeWave();
        this.Invalidate();
      
    

    private int waveWidth = 30;
    /// <summary>
    /// 水波纹宽度
    /// </summary>
    [DefaultValue(30)]
    [Description("水波纹宽度")]
    public int WaveWidth
    
      get  return this.waveWidth; 
      set
      
        if (this.waveWidth == value || value < 1)
          return;
        this.waveWidth = value;
        this.InitializeWave();
        this.Invalidate();
      
    

    private int waveHeight = 10;
    /// <summary>
    /// 水波纹高度
    /// </summary>
    [DefaultValue(10)]
    [Description("水波纹高度")]
    public int WaveHeight
    
      get  return this.waveHeight; 
      set
      
        if (this.waveHeight == value || value < 1)
          return;
        this.waveHeight = value;
        this.InitializeWave();
        this.Invalidate();
      
    

    private Color waveBackColor = Color.Empty;
    /// <summary>
    /// 水波纹背景颜色
    /// </summary>
    [DefaultValue(typeof(Color), "Empty")]
    [Description("水波纹背景颜色")]
    [Editor(typeof(ColorEditorExt), typeof(System.Drawing.Design.UITypeEditor))]
    public Color WaveBackColor
    
      get  return this.waveBackColor; 
      set
      
        if (this.waveBackColor == value)
          return;
        this.waveBackColor = value;
        this.Invalidate();
      
    

    private Color waveFrontColor = Color.FromArgb(104, 135, 206, 250);
    /// <summary>
    /// 水波纹前方颜色
    /// </summary>
    [DefaultValue(typeof(Color), "104, 135, 206, 250")]
    [Description("水波纹前方颜色")]
    [Editor(typeof(ColorEditorExt), typeof(System.Drawing.Design.UITypeEditor))]
    public Color WaveFrontColor
    
      get  return this.waveFrontColor; 
      set
      
        if (this.waveFrontColor == value)
          return;
        this.waveFrontColor = value;
        this.Invalidate();
      
    

    private Color waveBehindColor = Color.FromArgb(104, 135, 206, 250);
    /// <summary>
    /// 水波纹后方颜色
    /// </summary>
    [DefaultValue(typeof(Color), "104, 135, 206, 250")]
    [Description("水波纹后方颜色")]
    [Editor(typeof(ColorEditorExt), typeof(System.Drawing.Design.UITypeEditor))]
    public Color WaveBehindColor
    
      get  return this.waveBehindColor; 
      set
      
        if (this.waveBehindColor == value)
          return;
        this.waveBehindColor = value;
        this.Invalidate();
      
    

    #endregion

    #region 进度值

    private bool valueShow = true;
    /// <summary>
    /// 是否显示进度值
    /// </summary>
    [DefaultValue(true)]
    [Description("是否显示进度值")]
    public bool ValueShow
    
      get  return this.valueShow; 
      set
      
        if (this.valueShow == value)
          return;
        this.valueShow = value;
        this.Invalidate();
      
    

    private float value = 0.0f;
    /// <summary>
    /// 进度值(0-1)
    /// </summary>
    [DefaultValue(0.0f)]
    [Description("进度值")]
    public float Value
    
      get  return this.value; 
      set
      
        if (this.value == value)
          return;
        if (value > 1)
          value = 1;
        if (value < 0)
          value = 0;
        this.value = value;
        this.Invalidate();
        if (this.valueChanged != null)
        
          this.valueChanged(this, new ValueEventArgs()  Value = value );
        
      
    

    private Font valueFont = new Font("宋体", 13, FontStyle.Bold);
    /// <summary>
    /// 进度值字体
    /// </summary>
    [DefaultValue(typeof(Font), "13pt style=Bold")]
    [Description("进度值字体")]
    public Font ValueFont
    
      get  return this.valueFont; 
      set
      
        if (this.valueFont == value)
          return;
        this.valueFont = value;
        this.Invalidate();
      
    

    private Color valueColor = Color.FromArgb(183, 240, 128, 128);
    /// <summary>
    /// 进度值颜色
    /// </summary>
    [DefaultValue(typeof(Color), "183, 240, 128, 128")]
    [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();
      
    

    #endregion

    [Editor(typeof(ColorEditorExt), typeof(System.Drawing.Design.UITypeEditor))]
    public override Color BackColor
    
      get
      
        return base.BackColor;
      
      set
      
        base.BackColor = value;
      
    

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

    /// <summary>
    /// 水波纹移动定时器
    /// </summary>
    private Timer waveTimer;
    /// <summary>
    /// 水波纹移动距离
    /// </summary>
    int wave_distance = 0;
    /// <summary>
    /// 前面水波纹坐标
    /// </summary>
    List<Point> waveFrontPointList = new List<Point>();
    /// <summary>
    /// 后面水波纹坐标
    /// </summary>
    List<Point> waveBehindPointList = new List<Point>();

    #endregion

    public WaveProgressExt()
    
      SetStyle(ControlStyles.UserPaint, true);
      SetStyle(ControlStyles.AllPaintingInWmPaint, true);
      SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
      SetStyle(ControlStyles.ResizeRedraw, true);
      SetStyle(ControlStyles.SupportsTransparentBackColor, true);
      InitializeComponent();

      this.InitializeWave();

      this.waveTimer = new Timer();
      this.waveTimer.Interval = 100;
      this.waveTimer.Tick += new EventHandler(this.time_Tick);
    

    protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
    
      base.OnPaint(e);

      Graphics g = e.Graphics;
      Rectangle rect = e.ClipRectangle;
      g.SmoothingMode = SmoothingMode.AntiAlias;

      if (this.Type == WaveProgressType.Circle)
      
        GraphicsPath gp = new GraphicsPath();
        gp.AddEllipse(rect);
        g.SetClip(gp);
        gp.Dispose();
      

      #region 水波纹背景
      if (this.WaveBackColor != Color.Empty)
      
        SolidBrush waveback_sb = new SolidBrush(this.WaveBackColor);
        if (this.Type == WaveProgressType.Circle)
          g.FillEllipse(waveback_sb, new Rectangle(rect.X + 2, rect.Y + 2, rect.Width - 4, rect.Height - 4));
        else
          g.FillRectangle(waveback_sb, new Rectangle(rect.X, rect.Y, rect.Width - 2, rect.Height - 2));
        waveback_sb.Dispose();
      
      #endregion

      #region 水波纹
      if (this.waveFrontPointList.Count > 0)
      
        SolidBrush behind_sb = new SolidBrush(this.WaveBehindColor);
        SolidBrush front_sb = new SolidBrush(this.WaveFrontColor);

        Point[] behindPoint = new Point[this.waveFrontPointList.Count + 2];
        Point[] frontPoint = new Point[this.waveFrontPointList.Count + 2];

        int value_h = (int)(this.Value * rect.Height);
        for (int i = 0; i < this.waveFrontPointList.Count; i++)
        
          behindPoint[i] = new Point(this.waveBehindPointList[i].X - this.wave_distance, rect.Bottom - this.waveBehindPointList[i].Y - value_h + this.WaveHeight / 3);
          frontPoint[i] = new Point(this.waveFrontPointList[i].X + this.wave_distance, rect.Bottom - this.waveFrontPointList[i].Y - value_h);
        

        behindPoint[this.waveFrontPointList.Count] = new Point(behindPoint[this.waveFrontPointList.Count - 1].X, rect.Bottom);
        behindPoint[this.waveFrontPointList.Count + 1] = new Point(behindPoint[0].X, rect.Bottom);

        frontPoint[this.waveFrontPointList.Count] = new Point(frontPoint[this.waveFrontPointList.Count - 1].X, rect.Bottom);
        frontPoint[this.waveFrontPointList.Count + 1] = new Point(frontPoint[0].X, rect.Bottom);

        g.FillClosedCurve(behind_sb, behindPoint, FillMode.Alternate, this.WaveTension);
        g.FillClosedCurve(front_sb, frontPoint, FillMode.Alternate, this.WaveTension);
        front_sb.Dispose();
        behind_sb.Dispose();

        #region 进度值
        if (this.ValueShow)
        
          g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
          string value_str = (this.Value * 100).ToString("F0").PadLeft(3,  ) + "%";
          Size value_size = TextRenderer.MeasureText(value_str, this.ValueFont, new Size(), TextFormatFlags.NoPadding);
          Rectangle value_rect = new Rectangle((rect.Width - value_size.Width) / 2, (rect.Height - value_size.Height) / 2, value_size.Width, value_size.Height);
          TextRenderer.DrawText(g, value_str, this.ValueFont, value_rect, this.ValueColor, TextFormatFlags.NoPadding);
        
        #endregion

        #region 边框
        if (this.Type == WaveProgressType.Circle)
        
          //利用背景色消除锯齿
          Pen back_pen = new Pen(this.BackColor);
          g.DrawEllipse(back_pen, rect);
          back_pen.Dispose();

          if (this.BorderShow)
          
            Pen border_pen = new Pen(this.WaveFrontColor, 2);
            g.DrawEllipse(border_pen, new Rectangle(rect.X + 2, rect.Y + 2, rect.Width - 4, rect.Height - 4));
            border_pen.Dispose();
          
        
        else
        
          if (this.BorderShow)
          
            Pen border_pen = new Pen(this.WaveFrontColor, 2);
            g.DrawRectangle(border_pen, new Rectangle(rect.X, rect.Y, rect.Width - 2, rect.Height - 2));
            border_pen.Dispose();
          
        
        #endregion

      
      #endregion

    

    protected override void OnResize(EventArgs e)
    
      base.OnResize(e);
      this.InitializeWave();
    

    /// <summary>
    /// 水波纹移动动画
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void time_Tick(object sender, EventArgs e)
    
      this.wave_distance += this.WaveInterval;
      if (this.wave_distance >= this.WaveWidth * 2)
      
        this.wave_distance = 0;
      
      this.Invalidate();
    

    /// <summary>
    /// 初始化波浪纹
    /// </summary>
    protected void InitializeWave()
    
      this.waveFrontPointList.Clear();
      this.waveBehindPointList.Clear();
      int startFront_x = this.ClientRectangle.X - this.WaveWidth * 4;
      int start_y = 0;
      int startBehind_x = this.ClientRectangle.Right + this.WaveWidth * 4;

      int i = 0;
      while (true)
      
        startFront_x += this.WaveWidth;
        startBehind_x -= this.WaveWidth;
        start_y = this.WaveHeight * (i % 2);
        this.waveFrontPointList.Add(new Point(startFront_x, start_y));
        this.waveBehindPointList.Add(new Point(startBehind_x, start_y));
        if (startFront_x >= this.ClientRectangle.Right && start_y == 0)
        
          this.wave_distance = 0;
          return;
        
        i++;
      

    

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

    /// <summary>
    /// 外观类型
    /// </summary>
    [Description("外观类型")]
    public enum WaveProgressType
    
      /// <summary>
      /// 四边形
      /// </summary>
      Flat,
      /// <summary>
      /// 圆形
      /// </summary>
      Circle
    

    /// <summary>
    /// 进度值更改事件参数
    /// </summary>
    [Description("进度值更改事件参数")]
    public class ValueEventArgs : EventArgs
    
      /// <summary>
      /// 进度值
      /// </summary>
      [Description("进度值")]
      public float Value  get; set; 
    
  

源码下载:水波纹进度控件.zip

以上是关于水波纹进度控件----------WinForm控件开发系列的主要内容,如果未能解决你的问题,请参考以下文章

android 水波纹控件,仿京东语音评价动画

Android自定义控件-Path之贝赛尔曲线和手势轨迹水波纹效果

自定义控件三部曲之绘图篇(二十)——RadialGradient与水波纹按钮效果

wpf 水波进度条 用户控件

如何给Imageview 设置水波纹效果

自定义控件三部曲之绘图篇——Path之贝赛尔曲线和手势轨迹水波纹效果