c# 实现圆形的进度条(ProgressBar)

在我们实际的工作中可能经常使用到圆形的进度条,但是这是怎么实现的呢?其实这只不过是修改了一下ProgressBar的模板,我们在下面的代码中我们将ProgressBar的Value值绑定到Border的Background上面,并且使用了一个ValueToProcessConverter的转换器进行相应地转换,这里重点介绍一下这个转换器

<ProgressBar Name="pb" Minimum="0" Maximum="100" >
  <ProgressBar.Template>
    <ControlTemplate TargetType="ProgressBar">
     <Border Background="{TemplateBinding Value, Converter={StaticResource ValueToProcessConverter}, ConverterParameter=250}"/>
    </ControlTemplate>
  </ProgressBar.Template>
</ProgressBar>

下面介绍这部分的源码,并做简要的分析:

首先,获取ProgressBar.Value,然后再获取ConverterParameter=250这个值,通过这两个值就能确定画的圆环的大小和ProgressBar显示的值,然后我们再调用DrawBrush(arg, 100, radius, radius, Thickness)这个函数来进行绘制,具体代码如下:

private Brush DrawBrush(double value, double maxValue, double radiusX, double radiusY, double thickness)
        {
            DrawingGroup drawingGroup = new DrawingGroup();
            DrawingContext drawingContext = drawingGroup.Open();
            DrawingGeometry(drawingContext, value, maxValue, radiusX, radiusY, thickness);
            DrawingBrush brush = new DrawingBrush(drawingGroup);
            return brush;
        }

  这里需要注意的是绝不能直接实例化 DrawingContext;但可以通过某些方法(例如 DrawingGroup.Open 和 DrawingVisual.RenderOpen)获取绘图上下文。我们这里是使用DrawingGroup.Open的方法来进行相应的绘图,然后在里面调用里DrawingGeometry这个函数,在这个函数中开始绘制一些DrawEllipse和DrawGeometry,在这个函数中我们讲解一下FormattedText 这个类,使用 FormattedText 对象可以绘制多行文本,且可以单独对该文本中的每个字符设置格式。

private void DrawingGeometry(DrawingContext drawingContext, double value, double maxValue, double radiusX, double radiusY, double thickness)
       {
           drawingContext.DrawEllipse(null, new Pen(EllipseBrush, thickness), centerPoint, radiusX, radiusY);
           drawingContext.DrawGeometry(NormalBrush, new Pen(), GetGeometry(value, maxValue, radiusX, radiusY, thickness));
 
           FormattedText formatWords = new FormattedText(percentString, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, SuccessRateTypeface, SuccessRateFontSize, NormalBrush);
           Point startPoint = new Point(centerPoint.X - formatWords.Width / 2, centerPoint.Y - formatWords.Height / 2 - SuccessRateFontCorrectionValue);
           drawingContext.DrawText(formatWords, startPoint);
 
           drawingContext.Close();
       }  
public class ValueToProcessConverter : IValueConverter
    {
        readonly double Thickness = 20;
        private Point centerPoint;
        private double radius;
        readonly SolidColorBrush NormalBrush = new SolidColorBrush(Colors.White);
        readonly SolidColorBrush EllipseBrush = new SolidColorBrush(Color.FromRgb(107, 132, 165));
 
        string percentString;
        private static readonly Typeface SuccessRateTypeface;
        private const int SuccessRateFontSize = 65;
        readonly double SuccessRateFontCorrectionValue = 12;
 
        static ValueToProcessConverter()
        {
            SuccessRateTypeface = new Typeface(new FontFamily("MSYH"), new FontStyle(), new FontWeight(), new FontStretch());
        }
        public ValueToProcessConverter()
        {
 
        }
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is double && !string.IsNullOrEmpty((string)parameter))
            {
                double arg = (double)value;
                double width = double.Parse((string)parameter);
                radius = width / 2;
                centerPoint = new Point(radius, radius);
                return DrawBrush(arg, 100, radius, radius, Thickness);
            }
            else
            {
                throw new ArgumentException();
            }
        }
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
 
        /// <summary>
        /// 根据角度获取坐标
        /// </summary>
        /// <param name="CenterPoint"></param>
        /// <param name="r"></param>
        /// <param name="angel"></param>
        /// <returns></returns>
        private Point GetPointByAngel(Point CenterPoint, double r, double angel)
        {
            Point p = new Point();
            p.X = Math.Sin(angel * Math.PI / 180) * r + CenterPoint.X;
            p.Y = CenterPoint.Y - Math.Cos(angel * Math.PI / 180) * r;
            return p;
        }
 
        /// <summary>
        /// 根据4个坐标画出扇形
        /// </summary>
        /// <param name="bigFirstPoint"></param>
        /// <param name="bigSecondPoint"></param>
        /// <param name="smallFirstPoint"></param>
        /// <param name="smallSecondPoint"></param>
        /// <param name="bigRadius"></param>
        /// <param name="smallRadius"></param>
        /// <param name="isLargeArc"></param>
        /// <returns></returns>
        private Geometry DrawingArcGeometry(Point bigFirstPoint, Point bigSecondPoint, Point smallFirstPoint, Point smallSecondPoint, double bigRadius, double smallRadius, bool isLargeArc)
        {
            PathFigure pathFigure = new PathFigure { IsClosed = true };
            pathFigure.StartPoint = bigFirstPoint;
            pathFigure.Segments.Add(
              new ArcSegment
              {
                  Point = bigSecondPoint,
                  IsLargeArc = isLargeArc,
                  Size = new Size(bigRadius, bigRadius),
                  SweepDirection = SweepDirection.Clockwise
              });
            pathFigure.Segments.Add(new LineSegment { Point = smallSecondPoint });
            pathFigure.Segments.Add(
             new ArcSegment
             {
                 Point = smallFirstPoint,
                 IsLargeArc = isLargeArc,
                 Size = new Size(smallRadius, smallRadius),
                 SweepDirection = SweepDirection.Counterclockwise
             });
            PathGeometry pathGeometry = new PathGeometry();
            pathGeometry.Figures.Add(pathFigure);
 
            return pathGeometry;
        }
 
        /// <summary>
        /// 根据当前值和最大值获取扇形
        /// </summary>
        /// <param name="value"></param>
        /// <param name="maxValue"></param>
        /// <returns></returns>
        private Geometry GetGeometry(double value, double maxValue, double radiusX, double radiusY, double thickness)
        {
            bool isLargeArc = false;
            double percent = value / maxValue;
            percentString = string.Format("{0}%", Math.Round(percent * 100, 2));
            double angel = percent * 360D;
            if (angel > 180) isLargeArc = true;
            double bigR = radiusX + thickness / 2;
            double smallR = radiusX - thickness / 2;
            Point firstpoint = GetPointByAngel(centerPoint, bigR, 0);
            Point secondpoint = GetPointByAngel(centerPoint, bigR, angel);
            Point thirdpoint = GetPointByAngel(centerPoint, smallR, 0);
            Point fourpoint = GetPointByAngel(centerPoint, smallR, angel);
            return DrawingArcGeometry(firstpoint, secondpoint, thirdpoint, fourpoint, bigR, smallR, isLargeArc);
        }
 
        /// <summary>
        /// 画扇形
        /// </summary>
        /// <param name="drawingContext"></param>
        /// <param name="value"></param>
        /// <param name="maxValue"></param>
        /// <param name="radiusX"></param>
        /// <param name="radiusY"></param>
        /// <param name="thickness"></param>
        private void DrawingGeometry(DrawingContext drawingContext, double value, double maxValue, double radiusX, double radiusY, double thickness)
        {
            drawingContext.DrawEllipse(null, new Pen(EllipseBrush, thickness), centerPoint, radiusX, radiusY);
            drawingContext.DrawGeometry(NormalBrush, new Pen(), GetGeometry(value, maxValue, radiusX, radiusY, thickness));
            FormattedText formatWords = new FormattedText(percentString, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, SuccessRateTypeface, SuccessRateFontSize, NormalBrush);
            Point startPoint = new Point(centerPoint.X - formatWords.Width / 2, centerPoint.Y - formatWords.Height / 2 - SuccessRateFontCorrectionValue);
            drawingContext.DrawText(formatWords, startPoint);
            drawingContext.Close();
        }
 
        /// <summary>
        /// 根据当前值和最大值画出进度条
        /// </summary>
        /// <param name="value"></param>
        /// <param name="maxValue"></param>
        /// <returns></returns>
        private Brush DrawBrush(double value, double maxValue, double radiusX, double radiusY, double thickness)
        {
            DrawingGroup drawingGroup = new DrawingGroup();
            DrawingContext drawingContext = drawingGroup.Open();
            DrawingGeometry(drawingContext, value, maxValue, radiusX, radiusY, thickness);
            DrawingBrush brush = new DrawingBrush(drawingGroup);
            return brush;
        }
 
    }

以上就是c# 实现圆形的进度条(ProgressBar)的详细内容,更多关于c# 实现进度条的资料请关注我们其它相关文章!

(0)

相关推荐

  • C# Oracle批量插入数据进度条的实现代码

    前言 由于项目需求,需要将Excel中的数据进过一定转换导入仅Oracle数据库中.考虑到当Excel数据量较大时,循环Insert语句效率太低,故采用批量插入的方法.在插入操作运行时,会造成系统短暂的"卡死"现象.为了让用户知道插入的状态,需要制作一个进度条来显示插入的进度. 批量插入 项目中运用的是System.Data.OracleClient.首先将Excel数据通过转换函数转换为DataTable,其中的字段和数据库中相应表格的字段完全对应. public int Impor

  • C# Winform下载文件并显示进度条的实现代码

    方法一: 效果如下图所示: 代码如下: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace WinShowDown { public partial class F

  • C#实现带进度条的ListView

    推荐阅读:ListView 百分比进度条(delphi版) 对于已经有的组件,可以直接添加进来,添加后要先运行一下,然后会在工具箱内找到相应控件. 1.首先编写组件,然后将组件添加到工具箱内 编写代码如下: public partial class ListViewEx : System.Windows.Forms.ListView { public ListViewEx() { InitializeComponent(); } //C# listview进度条显示 private Color

  • C#实现炫酷启动图-动态进度条效果

    一.简述 最近接到一个新需求,让做一个动效进度条. 由于我们的产品比较大,在软件启动的时候会消耗比较长的时间,原生的进度条已经不能满足我们的需求,这里我们就需要一个会动的进度条,效果如下图所示. 光效进度条主要是做了一个进度动画,在已完成的部分上进行快速的迭代渲染,给用户一种直观感受,我们的软件一直努力加载,它还活着. 有了这个进度条之后,当我们的进度从40%到50%这个持续的过程中,界面再也不会出现假死的情况,是不是很完美呢... 下面我就来分析下这个动效进度条是怎么做的 二.动效进度条 如效

  • c#进度条 progressBar 使用方法的小例子

    复制代码 代码如下: using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using Mes.Core; namespace HCMDoImport{    public partial class ProcessBarForm : B

  • C#自定义音乐播放器进度条

    有些时候我们做的程序需要进度条,而vs提供的控件不是我们想要的.先看效果图: 进度条闪烁动画,当然背景可设为Transparent 之前想手绘进度条线条的,结果控件运行时会闪烁,所以直接用了panel控件 源码: [DefaultEvent("ProgressClick")] [ToolboxBitmap(typeof(TrackBar))] public partial class ProcessBar : UserControl { public ProcessBar() { //

  • c#根据文件大小显示文件复制进度条实例

    初学者,照着书上的抄袭制作,但已经理解了里面的意思和应用,并且进行了稍微改善和异常捕捉.这里记录下,以防以后用到这方面的知识点. 窗体设计: code: 复制代码 代码如下: using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.

  • asp.net(c#)开发中的文件上传组件uploadify的使用方法(带进度条)

    在Web开发中,有很多可以上传的组件模块,利用HTML的File控件的上传也是一种办法,不过这种方式,需要处理的细节比较多,而且只能支持单文件的操作.在目前Web开发中用的比较多的,可能uploadify(参考http://www.uploadify.com/)也算一个吧,不过这个版本一直在变化,他们的脚本调用也有很大的不同,甚至调用及参数都一直在变化,很早的时候,那个Flash的按钮文字还没法变化,本篇随笔主要根据项目实际,介绍一下3.1版本的uploadify的控件使用,这版本目前还是最新的

  • C#中常使用进度条的代码

    复制代码 代码如下: using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.Diagnostics; using System.Threading; namespace WindowsApplication2 { /// <summary> /// 

  • C#实现带百分比的进度条功能示例

    本文实例讲述了C#实现带百分比的进度条功能.分享给大家供大家参考,具体如下: 功能需求: 如果程序中会执行一个耗时的计算过程,我想在用户点击按钮后,弹出一个进度条窗口,显示正在执行的进度(最好能带有百分比),执行完成后,进度条窗口关闭,回到主程序窗口. 在关闭子窗口之前父窗体不能点击操作. 实现方法: 先设计Form2进度条窗体,在Form2中央上放ProgressBar控件progressBar1和Label控件label1,代码: public partial class Form2 : F

随机推荐