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) 的全部内容, 来源链接: utcz.com/z/338899.html

回到顶部