LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

C# 打造炫酷的WinForm水波进度控件:完整教程与源码分析

admin
2024年11月22日 14:31 本文热度 643

在WinForm应用程序开发中,一个富有视觉吸引力的用户界面往往能够提升用户体验。今天,我将为大家介绍一个如何自己手写一个的水波进度控件。

控件特性

  • 流畅的水波动画效果
  • 渐变色水波
  • 可自定义的边框样式
  • 阴影和高光效果
  • 实时进度显示

核心实现

1. 基础架构

public class WaveProgressControl : Control
{
    private float _progress = 0f;
    private float _targetProgress = 0f;
    private Timer _animationTimer;
    private Timer _waveTimer;
    private float _waveOffset = 0f;
}

控件继承自基础Control类,通过两个Timer实现水波动画和进度变化的平滑过渡。

2. 视觉定制选项

控件提供了丰富的自定义选项,包括:

  • 水波颜色(双色渐变)
  • 边框样式(颜色、宽度、线型)
  • 阴影效果
  • 高光效果
  • 文本颜色

3. 动画系统

private void InitializeTimers()
{
    _animationTimer = new Timer();
    _animationTimer.Interval = 16;
    _animationTimer.Tick += (s, e) =>
    {
        if (Math.Abs(_progress - _targetProgress) > 0.001f)
        {
            _progress += (_targetProgress - _progress) * ANIMATION_SPEED;
            Invalidate();
        }
    };
    _animationTimer.Start();

    _waveTimer = new Timer();
    _waveTimer.Interval = 16;
    _waveTimer.Tick += (s, e) =>
    {
        _waveOffset += 0.1f;
        if (_waveOffset > Math.PI * 2)
            _waveOffset = 0;
        Invalidate();
    };
    _waveTimer.Start();
}

采用双Timer机制:

  • animationTimer负责进度值的平滑过渡
  • waveTimer控制水波动画效果

4. 绘制过程

控件的绘制过程分为几个关键步骤:

阴影效果

// 绘制阴影效果  
if (EnableShade)
{
    using (GraphicsPath shadowPath = new GraphicsPath())
    {
        shadowPath.AddEllipse(circleRect);
        using (PathGradientBrush shadowBrush = new PathGradientBrush(shadowPath))
        {
            shadowBrush.CenterColor = ShadeColor;
            shadowBrush.SurroundColors = new Color[] { Color.Transparent };
            e.Graphics.FillPath(shadowBrush, shadowPath);
        }
    }
}

边框绘制

// 绘制外圆  
if (ShowBorder)
{
    using (GraphicsPath borderPath = new GraphicsPath())
    {
        borderPath.AddEllipse(circleRect);
        using (Pen borderPen = new Pen(BorderColor, BorderWidth))
        {

            borderPen.DashStyle = BorderStyle;
            e.Graphics.DrawPath(borderPen, borderPath);
        }
    }
}

水波效果

// 绘制水波  
int waveBottom = (int)(circleRect.Bottom - (circleRect.Height * currentProgress));

using (GraphicsPath wavePath = new GraphicsPath())
{
    Point[] points = new Point[circleRect.Width + 3];
    for (int x = 0; x <= circleRect.Width; x++)
    {
        int y = (int)(Math.Sin(x * 0.05f + _waveOffset) * WAVE_HEIGHT);
        points[x] = new Point(x + circleRect.X, waveBottom + y);
    }

    points[points.Length - 2] = new Point(circleRect.Right, circleRect.Bottom);
    points[points.Length - 1] = new Point(circleRect.Left, circleRect.Bottom);

    wavePath.AddLines(points);

    using (LinearGradientBrush brush = new LinearGradientBrush(
        circleRect,
        WaveColor1,
        WaveColor2,
        90f))
    {
        e.Graphics.FillPath(brush, wavePath);
    }
}

高光效果

// 绘制高光效果  
if (EnableHighlight)
{
    using (LinearGradientBrush highlightBrush = new LinearGradientBrush(
        circleRect,
        HighlightColor,
        Color.Transparent,
        45f))
    {
        e.Graphics.FillEllipse(highlightBrush, circleRect);
    }
}

完整代码

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

[ToolboxItem(true)]
[Description("水波浪进度控件")]
public class WaveProgressControl : Control
{
    private float _progress = 0f;
    private float _targetProgress = 0f;
    private Timer _animationTimer;
    private Timer _waveTimer;
    private float _waveOffset = 0f;
    private const float WAVE_HEIGHT = 10f;
    private const float ANIMATION_SPEED = 0.02f;

    #region 属性定义  

    // 基本属性  
    private Color _waveColor1 = Color.FromArgb(100181246);
    private Color _waveColor2 = Color.FromArgb(33150243);
    private Color _borderColor = Color.FromArgb(200200200);
    private float _borderWidth = 2f;
    private DashStyle _borderStyle = DashStyle.Solid;
    private bool _enableShade = true;
    private Color _shadeColor = Color.FromArgb(30000);
    private bool _enableHighlight = true;
    private Color _highlightColor = Color.FromArgb(30255255255);
    private Color _textColor = Color.FromArgb(646464);
    private bool _showBorder = true;

    [Category("Appearance")]
    [Description("第一个波浪颜色")]
    public Color WaveColor1
    {
        get => _waveColor1;
        set
        {
            _waveColor1 = value;
            Invalidate();
        }
    }

    [Category("Appearance")]
    [Description("第二个波浪颜色")]
    public Color WaveColor2
    {
        get => _waveColor2;
        set
        {
            _waveColor2 = value;
            Invalidate();
        }
    }

    [Category("Border")]
    [Description("边框颜色")]
    public Color BorderColor
    {
        get => _borderColor;
        set
        {
            _borderColor = value;
            Invalidate();
        }
    }

    [Category("Border")]
    [Description("边框宽度")]
    public float BorderWidth
    {
        get => _borderWidth;
        set
        {
            _borderWidth = value;
            Invalidate();
        }
    }

    [Category("Border")]
    [Description("边框样式")]
    public DashStyle BorderStyle
    {
        get => _borderStyle;
        set
        {
            _borderStyle = value;
            Invalidate();
        }
    }

    [Category("Border")]
    [Description("是否显示边框")]
    public bool ShowBorder
    {
        get => _showBorder;
        set
        {
            _showBorder = value;
            Invalidate();
        }
    }

    [Category("Effects")]
    [Description("启用阴影效果")]
    public bool EnableShade
    {
        get => _enableShade;
        set
        {
            _enableShade = value;
            Invalidate();
        }
    }

    [Category("Effects")]
    [Description("阴影颜色")]
    public Color ShadeColor
    {
        get => _shadeColor;
        set
        {
            _shadeColor = value;
            Invalidate();
        }
    }

    [Category("Effects")]
    [Description("启用高光效果")]
    public bool EnableHighlight
    {
        get => _enableHighlight;
        set
        {
            _enableHighlight = value;
            Invalidate();
        }
    }

    [Category("Effects")]
    [Description("高光颜色")]
    public Color HighlightColor
    {
        get => _highlightColor;
        set
        {
            _highlightColor = value;
            Invalidate();
        }
    }

    [Category("Appearance")]
    [Description("文本颜色")]
    public Color TextColor
    {
        get => _textColor;
        set
        {
            _textColor = value;
            Invalidate();
        }
    }

    [Category("Behavior")]
    [Description("当前进度值(0-1)")]
    [DefaultValue(0f)]
    public float Progress
    {
        get => _targetProgress;
        set
        {
            if (value < 0f) value = 0f;
            if (value > 1f) value = 1f;
            _targetProgress = value;
        }
    }

    #endregion

    public WaveProgressControl()
    
{
        Size = new Size(100100);

        SetStyle(ControlStyles.DoubleBuffer |
                ControlStyles.UserPaint |
                ControlStyles.AllPaintingInWmPaint |
                ControlStyles.OptimizedDoubleBuffer |
                ControlStyles.ResizeRedraw |
                ControlStyles.SupportsTransparentBackColor,
                true);

        if (!DesignMode)
        {
            InitializeTimers();
        }
    }

    private void InitializeTimers()
    
{
        _animationTimer = new Timer();
        _animationTimer.Interval = 16;
        _animationTimer.Tick += (s, e) =>
        {
            if (Math.Abs(_progress - _targetProgress) > 0.001f)
            {
                _progress += (_targetProgress - _progress) * ANIMATION_SPEED;
                Invalidate();
            }
        };
        _animationTimer.Start();

        _waveTimer = new Timer();
        _waveTimer.Interval = 16;
        _waveTimer.Tick += (s, e) =>
        {
            _waveOffset += 0.1f;
            if (_waveOffset > Math.PI * 2)
                _waveOffset = 0;
            Invalidate();
        };
        _waveTimer.Start();
    }

    protected override void OnHandleCreated(EventArgs e)
    
{
        base.OnHandleCreated(e);
        if (!DesignMode)
        {
            InitializeTimers();
        }
    }

    protected override void OnHandleDestroyed(EventArgs e)
    
{
        if (!DesignMode)
        {
            _animationTimer?.Stop();
            _waveTimer?.Stop();
        }
        base.OnHandleDestroyed(e);
    }

    protected override void OnPaint(PaintEventArgs e)
    
{
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
        e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
        e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
        e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
        e.Graphics.CompositingQuality = CompositingQuality.HighQuality;

        int size = Math.Min(Width, Height);
        int padding = 10;
        Rectangle circleRect = new Rectangle(padding, padding, size - padding * 2, size - padding * 2);

        // 计算当前进度  
        float currentProgress = DesignMode ? Progress : _progress;

        // 绘制阴影效果  
        if (EnableShade)
        {
            using (GraphicsPath shadowPath = new GraphicsPath())
            {
                shadowPath.AddEllipse(circleRect);
                using (PathGradientBrush shadowBrush = new PathGradientBrush(shadowPath))
                {
                    shadowBrush.CenterColor = ShadeColor;
                    shadowBrush.SurroundColors = new Color[] { Color.Transparent };
                    e.Graphics.FillPath(shadowBrush, shadowPath);
                }
            }
        }

        // 绘制外圆  
        if (ShowBorder)
        {
            using (GraphicsPath borderPath = new GraphicsPath())
            {
                borderPath.AddEllipse(circleRect);
                using (Pen borderPen = new Pen(BorderColor, BorderWidth))
                {

                    borderPen.DashStyle = BorderStyle;
                    e.Graphics.DrawPath(borderPen, borderPath);
                }
            }
        }

        // 创建圆形裁剪区域  
        using (GraphicsPath clipPath = new GraphicsPath())
        {
            clipPath.AddEllipse(circleRect);
            e.Graphics.SetClip(clipPath);

            // 绘制水波  
            int waveBottom = (int)(circleRect.Bottom - (circleRect.Height * currentProgress));

            using (GraphicsPath wavePath = new GraphicsPath())
            {
                Point[] points = new Point[circleRect.Width + 3];
                for (int x = 0; x <= circleRect.Width; x++)
                {
                    int y = (int)(Math.Sin(x * 0.05f + _waveOffset) * WAVE_HEIGHT);
                    points[x] = new Point(x + circleRect.X, waveBottom + y);
                }

                points[points.Length - 2] = new Point(circleRect.Right, circleRect.Bottom);
                points[points.Length - 1] = new Point(circleRect.Left, circleRect.Bottom);

                wavePath.AddLines(points);

                using (LinearGradientBrush brush = new LinearGradientBrush(
                    circleRect,
                    WaveColor1,
                    WaveColor2,
                    90f))
                {
                    e.Graphics.FillPath(brush, wavePath);
                }
            }

            // 绘制高光效果  
            if (EnableHighlight)
            {
                using (LinearGradientBrush highlightBrush = new LinearGradientBrush(
                    circleRect,
                    HighlightColor,
                    Color.Transparent,
                    45f))
                {
                    e.Graphics.FillEllipse(highlightBrush, circleRect);
                }
            }

            e.Graphics.ResetClip();
        }

        // 绘制百分比文本  
        string percentText = $"{(currentProgress * 100):F0}%";
        using (Font font = new Font("Arial", size / 8))
        {
            SizeF textSize = e.Graphics.MeasureString(percentText, font);
            PointF textPos = new PointF(
                circleRect.X + (circleRect.Width - textSize.Width) / 2,
                circleRect.Y + (circleRect.Height - textSize.Height) / 2
            );

            using (Brush textBrush = new SolidBrush(TextColor))
            {
                e.Graphics.DrawString(percentText, font, textBrush, textPos);
            }
        }

        base.OnPaint(e);
    }

    protected override void Dispose(bool disposing)
    
{
        if (disposing)
        {
            _animationTimer?.Dispose();
            _waveTimer?.Dispose();
        }
        base.Dispose(disposing);
    }
}

总结

这个水波进度控件不仅提供了醒目的视觉效果,还具有良好的可定制性和性能表现。它适用于需要展示进度信息的各种场景,能够为您的WinForm应用增添一份独特的视觉魅力。


该文章在 2024/11/22 17:04:11 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2024 ClickSun All Rights Reserved