永不停止的进度条






4.36/5 (33投票s)
一个用于您不知道过程需要多长时间的进度条。
引言
有时候你就是不知道事情会持续多久。 就像你妻子说她只会在杂货店待几分钟... 你懂我的意思。
Visual Studio 附带的标准ProgressBar
对于您知道某事需要多长时间或者可以确定一个过程有多少步骤的情况非常有用。 但就像你和你妻子去商店一样,有时你就是不知道事情会持续多久。 这就是我创建这个进度条的原因。
代码
该控件非常简单,它所做的就是使用标准Graphics
方法绘制到一个Rectangle
对象中。
Private Sub OSProgressBar_Paint(ByVal sender As Object, _
ByVal e As System.Windows.Forms.PaintEventArgs) _
Handles MyBase.Paint
Me._Graphics = e.Graphics
Me._Graphics.SmoothingMode = Drawing2D.SmoothingMode.HighSpeed
'this stops some of the redraw flickering at higher speeds
If _RequireClear Then
Me._Graphics.Clear(Me.BackColor)
End If
DrawBackGround()
End Sub
Private Sub PositionIndicator(ByVal Rect As Rectangle)
If Not IsNothing(Me._PointImage) AndAlso Me._ProgressType = _
OSProgressTypeConstants.osGRAPHICTYPE Then
Me._Graphics.DrawImage(Me._PointImage, Rect)
Else
Select Case Me._ProgressBoxStyle
Case OSProgressBoxStyleConstants.osSOLIDSAMESIZE
Dim R2 As New Rectangle(Rect.Left + 3, _
Rect.Top + 3, Rect.Width - 5, Rect.Height - 5)
Me._Graphics.FillRectangle(New SolidBrush(_IndicatorColor), R2)
Case OSProgressBoxStyleConstants.osBOXAROUND
Me._Graphics.DrawRectangle(New Pen(_IndicatorColor), Rect)
Dim R2 As New Rectangle(Rect.Left + 3, Rect.Top + 3, _
Rect.Width - 5, Rect.Height - 5)
Me._Graphics.FillRectangle(New SolidBrush(_IndicatorColor), R2)
Case OSProgressBoxStyleConstants.osSOLIDBIGGER
Me._Graphics.FillRectangle(New SolidBrush(_IndicatorColor), Rect)
Case OSProgressBoxStyleConstants.osSOLIDSMALLER
Dim R2 As New Rectangle(Rect.Left + 5, Rect.Top + 5, _
Rect.Width - 9, Rect.Height - 9)
Me._Graphics.FillRectangle(New SolidBrush(_IndicatorColor), R2)
End Select
End If
End Sub
Private Sub DrawBackGround()
Me._NumPoints = 0
If Me.Width > 0 And Me.Height > 0 Then
If Me._ShowBorder Then
Me._Graphics.DrawRectangle(New Pen(SystemColors.ActiveBorder), _
New Rectangle(0, 0, Me.Width - 1, Me.Height - 1))
End If
Dim iBoxSize As Integer = Me.Height * 0.75
Dim iBoxLeft As Integer = iBoxSize / 2
If iBoxSize > 3 Then
Do
'entire area Rectangle for the background image
Dim r As New Rectangle(iBoxLeft, 0, Me.Height - 1, Me.Height - 1)
If r.Left + r.Width > Me.Width Then
Exit Do
End If
If Me._NumPoints = Me._Position Then
'draw position indicator in full rectagle
PositionIndicator(r)
Else
'this will be the rectangle where
'the background image is drawn
Dim R2 As New Rectangle(r.Left + 3, r.Top + 3, _
r.Width - 6, r.Height - 6)
If Not IsNothing(Me._NormalImage) AndAlso Me._ProgressType = _
OSProgressTypeConstants.osGRAPHICTYPE Then
Me._Graphics.DrawImage(Me._NormalImage, R2)
Else
Me._Graphics.FillRectangle(New SolidBrush(Me.ForeColor), R2)
End If
End If
iBoxLeft += (iBoxSize * 1.5)
Me._NumPoints += 1
Loop
End If
End If
End Sub
Private Sub OSProgressBar_Resize(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.Resize
Me._RequireClear = True
'invalidate the control
Me.Invalidate()
End Sub
Private Sub tmrAutoProgress_Tick(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles tmrAutoProgress.Tick
If Me._Position = Me._NumPoints - 1 Then
If Me._ProgressStyle = OSProgressStyleConstants.osLEFTTORIGHT Then
Me._Position = 0
Else
Me._Position -= 1
Me._Increasing = False
End If
ElseIf Me._Position = 0 And Not Me._Increasing Then
Me._Position += 1
Me._Increasing = True
Else
If Me._Increasing Then
Me._Position += 1
Else
Me._Position -= 1
End If
End If
Me._RequireClear = False
Me.Invalidate()
End Sub
用户可以选择四种类型中的一种绘制标准方框(与背景框相同大小、更小、更大或带框更小),或者用户可以选择使用图像(图标效果最佳)作为背景和位置指示器。
矩形大小和位置数量由控件放置在表单上的高度决定。 例如,如果控件很高,则矩形会更少,但会更大。 另外,如果它很短,则矩形会更多,更小。 目前,该控件只有在水平(宽度大于高度)时才能正常运行,但我认为修改垂直操作的代码不会太难。
对于方框类型进度条,开发人员可以设置BackGroundColor
、ForeGroundColor
(背景框的颜色)、IndicatorColor
(位置框的颜色)。 对于图形类型进度条,可以设置NormalImage
(背景图像)和PointImage
(位置图像)图像。
开发人员可以确定控件是否“自动前进”,也就是说,如果它自动更改位置直到开发人员停止它。 如果启用了AutoProgress
,则还会用到另外两个属性; AutoProgressSpeed
和ProgressStyle
。 速度是不言自明的,1是慢的,255是快的。 ProgressStyle
属性确定当指示器到达最后一点时,它是否从第一点开始,或者调头并朝另一个方向前进。 当然,开发人员也可以根据需要手动设置位置。
关于显示进度类型控件的说明。 如果您有一个您无法控制的长时间运行的过程,则当前线程可能会在此过程中被阻塞。 我在序列化和反序列化类时发现了这一点。 在这种情况下,您在同一线程中运行的任何方法也将被阻塞。 我为此尝试过动画 GIF,当阻塞发生时它们也会停止动画。 有必要在调用阻塞函数之前生成一个新线程,然后显示必要的进度指示器。