Public Class GradedProgressBar
    Dim min As Integer
    Dim max As Integer
    Dim thresh1 As Integer
    Dim thresh2 As Integer
    Dim val As Integer
    Dim barcolor As Color


    Public Sub New()

        ' me call is required by the Windows Form Designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        min = 0
        max = 50
        thresh1 = 40
        thresh2 = 30
        val = 0
        barcolor = color.Blue

    End Sub

    Property Threshold1() As Integer
        Get
            Threshold1 = thresh1
        End Get
        Set(ByVal value As Integer)
            thresh1 = value
        End Set
    End Property

    Property Threshold2() As Integer
        Get
            Threshold2 = thresh2
        End Get
        Set(ByVal value As Integer)
            thresh2 = value
        End Set
    End Property

    Property Minimum() As Integer
        Get
            Minimum = min
        End Get
        Set(ByVal value As Integer)

            ' Prevent a negative value.
            If (value < 0) Then min=0

                ' Make sure that the minimum value is never set higher than the maximum value.
            If (value > max) Then min = value

            ' Ensure value is still in range
            If (val < min) Then val = min

            ' Invalidate the control to get a repaint.
            Me.Invalidate()
        End Set
    End Property

    Property Maximum() As Integer
        Get
            Maximum = max
        End Get
        Set(ByVal value As Integer)
            If (value < min) Then min = value
            max = value

            ' Make sure that value is still in range.
            If (val > max) Then val = max

            ' Invalidate the control to get a repaint.
            Me.Invalidate()

        End Set
    End Property

    Property Value() As Integer
        Get
            Value = val
        End Get
        Set(ByVal value As Integer)

            Dim oldValue As Integer = value
            If (value < min) Then
                val = min
            ElseIf (value > max) Then
                val = max
            Else
                val = value
            End If

            Caption.Text = (val / (max - min) * 100).ToString & "%"

            ' Invalidate only the changed area.
            Dim percent As Single
            Dim newValueRect As Rectangle = Me.ClientRectangle
            Dim oldValueRect As Rectangle = Me.ClientRectangle

            ' Use a new value to calculate the rectangle for progress.
            percent = (val - min) / (max - min)
            newValueRect.Width = (newValueRect.Width * percent)

            ' Use an old value to calculate the rectangle for progress.
            percent = (oldValue - min) / (max - min)
            oldValueRect.Width = (oldValueRect.Width * percent)

            Dim updateRect As New Rectangle

            ' Find only the part of the screen that must be updated.
            If (newValueRect.Width > oldValueRect.Width) Then
                updateRect.X = oldValueRect.Size.Width
                updateRect.Width = newValueRect.Width - oldValueRect.Width
            Else
                updateRect.X = newValueRect.Size.Width
                updateRect.Width = oldValueRect.Width - newValueRect.Width
            End If

            updateRect.Height = Me.Height

            ' Invalidate the intersection region only.
            Me.Invalidate(updateRect)

        End Set
    End Property

    Private Sub GradedProgressBar_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
        Dim g As Graphics = e.Graphics
        Dim percentv As Single = (val - min) / (max - min)
        Dim percentt1 As Single = thresh1 / (max - min)
        Dim percentt2 As Single = thresh2 / (max - min)
        Dim percent As Single
        Dim rect As Rectangle = Me.ClientRectangle

        ' Calculate area for drawing the progress.
        rect.Width = rect.Width * percentv

        Dim brush As New SolidBrush(barcolor)


        ' Draw the progress meter.
        For i As Integer = min To max
            percent = (i - min) / (max - min)
            If percent < percentv Then
                Select Case percent
                    Case Is > percentt2
                        brush.Color = Color.Red
                    Case Is > percentt1
                        brush.Color = Color.Orange
                    Case Else
                        brush.Color = Color.Green
                End Select

                rect.X = Me.ClientRectangle.Width / (max - min) * (i - min)
                rect.Width = Me.ClientRectangle.Width / (max - min) * 0.8
                g.FillRectangle(brush, rect)
            End If
        Next

        ' Draw a three-dimensional border around the control.
        Draw3dBorder(g)

        ' Clean up.
        brush.Dispose()
        g.Dispose()
    End Sub


    Private Sub GradedProgressBar_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
        ' Invalidate the control to get a repaint.
        With Caption
            .Left = 0
            .Height = 0
            .Width = Me.ClientRectangle.Width
            .Height = Me.ClientRectangle.Height
        End With

        Me.Invalidate()
    End Sub

    Private Sub Draw3dBorder(ByVal g As Graphics)
        Dim PenWidth As Integer = Pens.White.Width

        g.DrawLine(Pens.DarkGray, _
         New Point(Me.ClientRectangle.Left, Me.ClientRectangle.Top), _
         New Point(Me.ClientRectangle.Width - PenWidth, Me.ClientRectangle.Top))
        g.DrawLine(Pens.DarkGray, _
         New Point(Me.ClientRectangle.Left, Me.ClientRectangle.Top), _
         New Point(Me.ClientRectangle.Left, Me.ClientRectangle.Height - PenWidth))
        g.DrawLine(Pens.White, _
         New Point(Me.ClientRectangle.Left, Me.ClientRectangle.Height - PenWidth), _
         New Point(Me.ClientRectangle.Width - PenWidth, Me.ClientRectangle.Height - PenWidth))
        g.DrawLine(Pens.White, _
         New Point(Me.ClientRectangle.Width - PenWidth, Me.ClientRectangle.Top), _
         New Point(Me.ClientRectangle.Width - PenWidth, Me.ClientRectangle.Height - PenWidth))
    End Sub


End Class

