WinForm断续进度条自定义实现

    6

这段时间用WinForm写了一个断续进度条,以下是代码示例。

  public partial class SegmentProgressBar : UserControl
  {
      private const int MINIMUM_SEGMENTS = 1;
      private int maximumSegments;
      private bool showBorder = true;
      private bool showText = true;
      private Color borderColor = Color.Black;
      private Color textColor = Color.White;
      private Color notStartedColor = Color.LightGray;
      private Color failedColor = Color.Red;
      private Color inProgressColor = Color.Yellow;
      private Color completedColor = Color.Green;
      private string text;
      private SegmentState[] segments;
      private int updateIndex;
      public int UpdateProgressBarTimes { get; set; } = 3;
      public bool OnlyUpdateMustArea = false;
      public SegmentProgressBar()
      {
          InitializeComponent();
          Reset();
          this.DoubleBuffered = true;
          this.SetStyle(ControlStyles.ResizeRedraw, true);
          this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
      }

      private void Reset()
      {
          //ensure maximum segments is at least 1...
          this.maximumSegments = Math.Max(1, this.maximumSegments);

          this.segments = new SegmentState[maximumSegments];
          this.Invalidate();
      }

      public void UpdateSegment(int index, SegmentState state)
      {
          if (index >= 0 && index < maximumSegments)
          {
              if (this.segments[index] != state)
              {
                  this.segments[index] = state;
                
                  if (updateIndex>UpdateProgressBarTimes)
                  {
                      if (OnlyUpdateMustArea)
                      {
                          // 仅重绘改变状态的段的区域
                          float segmentWidth = (float)this.Width / this.segments.Length;
                          Rectangle invalidRect = new Rectangle(
                              (int)(index * segmentWidth),
                              0,
                              (int)segmentWidth,
                              this.Height);
                          this.Invalidate(invalidRect);
                      }
                      else
                      {
                          this.Invalidate();
                      }
                      updateIndex = 0;
                  }
                  else
                  {
                      updateIndex++;
                  }
                
              }
              return;
          }
         // throw new IndexOutOfRangeException("...");
      }
      protected override void OnPaint(PaintEventArgs e)
      {
          base.OnPaint(e);
          float segmentWidth = (float)this.Width / this.segments.Length;
          int startSegment = (int)(e.ClipRectangle.Left / segmentWidth);
          int endSegment = (int)Math.Ceiling((float)e.ClipRectangle.Right / segmentWidth);

          if (OnlyUpdateMustArea)
          {
              // 仅重绘被标记为无效的段
              for (int j = startSegment; j < Math.Min(endSegment, this.segments.Length); j++)
              {
                  float x = j * segmentWidth;
                  e.Graphics.FillRectangle(new SolidBrush(ColorFromSegmentState(this.segments[j])), x, 0, segmentWidth, this.Height);
              }
          }
          else
          {
              DrawSegments(e.Graphics);
          }
        

          if (ShowText) DrawText(e.Graphics);
          if (ShowBorder) DrawBorder(e.Graphics);
      }
      //protected override void OnPaint(PaintEventArgs e)
      //{
      //    base.OnPaint(e);
      //    DrawSegments(e.Graphics);
      //    if (ShowText)
      //    {
      //        DrawText(e.Graphics);
      //    }
      //    if (ShowBorder)
      //    {
      //        DrawBorder(e.Graphics);
      //    }
      //}

      protected override void OnResize(EventArgs e)
      {
          base.OnResize(e);
          this.Invalidate();
      }

      private void DrawBorder(Graphics g)
      {
          g.DrawRectangle(new Pen(Color.Black), 0, 0, this.Width - 1, this.Height - 1);
      }

      private void DrawText(Graphics g)
      {
          SizeF textSize = g.MeasureString(this.Text, this.Font);
          g.DrawString(this.text, this.Font, new SolidBrush(TextColor), new Point((int)(this.Width / 2 - textSize.Width / 2), (int)(this.Height / 2 - textSize.Height / 2)));
      }

      //private void DrawSegments(Graphics g)
      //{
      //    //these must be cast as float to have the sum a float, otherwise it rounds down to int
      //    float segmentWidth =(float)this.Width / (float)this.segments.Length;

      //    for (int j = 0; j < this.segments.Length; j++)
      //    {
      //        float x = j * segmentWidth;
      //        g.FillRectangle(new SolidBrush(ColorFromSegmentState(this.segments[j])), x, 0, segmentWidth, this.Height);
      //    }
      //}
      private void DrawSegments(Graphics g)
      {
          int totalWidth = this.Width;
          int totalSegments = this.segments.Length;

          for (int j = 0; j < totalSegments; j++)
          {
              // 计算每个段的宽度,确保最后一个段能够填满剩余空间
              float x = (float)totalWidth * j / totalSegments;
              float nextX = (float)totalWidth * (j + 1) / totalSegments;
              float segmentWidth = nextX - x;

              g.FillRectangle(new SolidBrush(ColorFromSegmentState(this.segments[j])), x, 0, segmentWidth, this.Height);
          }
      }
      private Color ColorFromSegmentState(SegmentState state)
      {
          switch (state)
          {
              default:
              case SegmentState.NOT_STARTED:
                  return NotStartedColor;
              case SegmentState.IN_PROGRESS:
                  return InProgressColor;
              case SegmentState.COMPLETED:
                  return CompletedColor;
              case SegmentState.FAILED:
                  return FailedColor;
          }
      }

      [Description("Maximum segments of the progress bar."), DefaultValue(100), Browsable(true)]
      public int MaximumSegments
      {
          get { return this.maximumSegments; }
          set
          {
              if (value < MINIMUM_SEGMENTS)
              {
                  throw new Exception("Minimum segment value must be at least 1");
              }

              this.maximumSegments = value; this.Reset();
          }
      }

      [Description("Is the border shown?"), DefaultValue(true), Browsable(true)]
      public bool ShowBorder
      {
          get { return this.showBorder; }
          set { this.showBorder = value; this.Invalidate(); }
      }

      [Description("Is the text shown?"), DefaultValue(true), Browsable(true)]
      public bool ShowText
      {
          get { return this.showText; }
          set { this.showText = value; this.Invalidate(); }
      }

      [Description("Color of the border."), Category("Progress"), Browsable(true)]
      public Color BorderColor
      {
          get { return this.borderColor; }
          set { this.borderColor = value; this.Invalidate(); }
      }

      [Description("Color of the text."), Category("Progress"), Browsable(true)]
      public Color TextColor
      {
          get { return this.textColor; }
          set { this.textColor = value; this.Invalidate(); }
      }

      [Description("Color of non-started segments."), Category("Progress"), Browsable(true)]
      public Color NotStartedColor
      {
          get { return this.notStartedColor; }
          set { this.notStartedColor = value; this.Invalidate(); }
      }

      [Description("Color of working segments."), Category("Progress"), Browsable(true)]
      public Color InProgressColor
      {
          get { return this.inProgressColor; }
          set { this.inProgressColor = value; this.Invalidate(); }
      }

      [Description("Color of completed segments."), Category("Progress"), Browsable(true)]
      public Color CompletedColor
      {
          get { return this.completedColor; }
          set { this.completedColor = value; this.Invalidate(); }
      }

      [Description("Color of failed segments."), Category("Progress"), Browsable(true)]
      public Color FailedColor
      {
          get { return this.failedColor; }
          set { this.failedColor = value; this.Invalidate(); }
      }

      [Description("Text value of the progress bar."), Category("Progress"), Browsable(true)]
      public override string Text
      {
          get { return this.text; }
          set { this.text = value; this.Invalidate(); }
      }

      public int SegmentsCompleted
      {
          get
          {
              return GetSegmentsOfType(SegmentState.COMPLETED);
          }
      }

      public int SegmentsFailed
      {
          get
          {
              return GetSegmentsOfType(SegmentState.FAILED);
          }
      }

      public int SegmentsInProgress
      {
          get
          {
              return GetSegmentsOfType(SegmentState.IN_PROGRESS);
          }
      }

      public int SegmentsNotStarted
      {
          get
          {
              return GetSegmentsOfType(SegmentState.NOT_STARTED);
          }
      }

      private int GetSegmentsOfType(SegmentState state)
      {
          int total = 0;

          foreach (SegmentState setState in this.segments)
          {
              if (setState == state)
              {
                  total++;
              }
          }

          return total;
      }

      public void ClearProgressBar()
      {
          for (int i = 0; i < maximumSegments; i++)
          {
              segments[i] = SegmentState.NOT_STARTED;
          }
          Invalidate();
      }
  }

Comments | 0 评论
消息盒子

# 暂无消息 #

只显示最新10条未读和已读信息