Imports System.ComponentModel
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.ComponentModel.Design

#Region " Enumerations "

''' <summary>
''' Defines the value for gradient view.
''' </summary>
Public Enum GradientEnum
    None
    Horizontal
    Vertical
    ForwardDiagonal
    BackwardDiagonal
    CustomAngle
    Continuous
    Rainbow
End Enum

''' <summary>
''' Hatch values. This is similar to <see cref="T:System.Drawing.Drawing2D.HatchStyle" /> enumeration except that, this enum has None value.
''' </summary>
Public Enum HatchEnum
    None = -1
    BackwardDiagonal = 3
    Cross = 4
    DarkDownwardDiagonal = 20
    DarkHorizontal = 29
    DarkUpwardDiagonal = 21
    DarkVertical = 28
    DashedDownwardDiagonal = 30
    DashedHorizontal = 32
    DashedUpwardDiagonal = 31
    DashedVertical = 33
    DiagonalBrick = 38
    DiagonalCross = 5
    Divot = 42
    DottedDiamond = 44
    DottedGrid = 43
    ForwardDiagonal = 2
    Horizontal = 0
    HorizontalBrick = 39
    LargeCheckerBoard = 50
    LargeConfetti = 35
    LargeGrid = 4
    LightDownwardDiagonal = 18
    LightHorizontal = 25
    LightUpwardDiagonal = 19
    LightVertical = 24
    Max = 4
    Min = 0
    NarrowHorizontal = 27
    NarrowVertical = 26
    OutlinedDiamond = 51
    Percent05 = 6
    Percent10 = 7
    Percent20 = 8
    Percent25 = 9
    Percent30 = 10
    Percent40 = 11
    Percent50 = 12
    Percent60 = 13
    Percent70 = 14
    Percent75 = 15
    Percent80 = 16
    Percent90 = 17
    Plaid = 41
    Shingle = 45
    SmallCheckerBoard = 49
    SmallConfetti = 34
    SmallGrid = 48
    SolidDiamond = 52
    Sphere = 47
    Trellis = 46
    Vertical = 1
    Wave = 37
    Weave = 40
    WideDownwardDiagonal = 22
    WideUpwardDiagonal = 23
    ZigZag = 36
End Enum
#End Region

''' <summary>
''' A custom progress bar.
''' </summary>
''' <remarks>Remember this is NOT derived from <see cref="T:System.Windows.Forms.ProgressBar" />.</remarks>
<ToolboxBitmap(GetType(ProgressBar)), Description("A customized progress bar."), Designer(GetType(ProgressBarDesigner))> _
Public Class ProgressBar
    Inherits System.Windows.Forms.UserControl

    Dim clMax, clMin, clVal As Long
    Dim ciStep As Integer
    Dim cbPer As Boolean
    Dim ccolBar1, ccolBar2 As Color
    Dim csgGrad As GradientEnum
    Dim csAngle As Single
    Dim cbAScale, cbFill, cbText As Boolean
    Dim cshHatch As HatchEnum
    Dim ccaText As ContentAlignment
    Dim cGrd As New Mitul.Gradient
    Dim cbAlpha As Byte
    Dim csbsBorder As System.Windows.Forms.Border3DStyle

#Region " Windows Form Designer generated code "

    ''' <summary>
    ''' Initializes a new instance of the <see cref="ProgressBar" /> class.
    ''' </summary>
    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call
        SetStyle( _
         ControlStyles.AllPaintingInWmPaint Or _
         ControlStyles.DoubleBuffer Or _
         ControlStyles.UserPaint Or _
         ControlStyles.ResizeRedraw Or _
         ControlStyles.SupportsTransparentBackColor, _
         True _
         )

        clMax = 100
        clMin = 0
        clVal = 0
        ciStep = 1
        cbPer = False
        ccolBar1 = Color.Blue
        ccolBar2 = Color.LimeGreen
        csgGrad = GradientEnum.None
        csAngle = 0
        cbAScale = True
        cshHatch = HatchEnum.None
        ccaText = ContentAlignment.MiddleCenter
        cbFill = False
        cbText = True
        cbAlpha = 255
        csbsBorder = Border3DStyle.Adjust
        MyBase.TabStop = False
    End Sub

    'UserControl overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.SuspendLayout()
        '
        'myProgressBar
        '
        Me.BackColor = System.Drawing.SystemColors.Control
        Me.Name = "myProgressBar"
        Me.Size = New System.Drawing.Size(350, 24)
        Me.ResumeLayout(False)

    End Sub

#End Region

#Region " Control Properties "

    ''' <summary>
    ''' Gets or sets the maximum value of the range of the control. 
    ''' </summary>
    ''' <value>The maximum.</value>
    <DefaultValue(100L), Category("Behavior"), _
    RefreshProperties(RefreshProperties.All), _
    Description("The upper bound of the range this ProgressBar is working with.")> _
    Public Property Maximum() As Long
        Get
            Return clMax
        End Get
        Set(ByVal Value As Long)
            clMax = Value
        End Set
    End Property

    ''' <summary>
    ''' Gets or sets the minimum value of the range of the control. 
    ''' </summary>
    ''' <value>The minimum.</value>
    <DefaultValue(0L), Category("Behavior"), _
    RefreshProperties(RefreshProperties.All), _
    Description("The lower bound of the range this ProgressBar is working with.")> _
    Public Property Minimum() As Long
        Get
            Return clMin
        End Get
        Set(ByVal Value As Long)
            clMin = Value
        End Set
    End Property

    ''' <summary>
    ''' Gets or sets the amount by which a call to the <see cref="PerformStep" /> method increases the current position of the progress bar. 
    ''' </summary>
    ''' <value>The step.</value>
    <DefaultValue(1I), Category("Behavior"), _
    RefreshProperties(RefreshProperties.All), _
    Description("The amount to increment the current value of the control by when the PerformStep() method is called.")> _
    Public Property [Step]() As Integer
        Get
            Return ciStep
        End Get
        Set(ByVal Value As Integer)
            ciStep = Value
        End Set
    End Property

    ''' <summary>
    ''' Gets or sets the current position of the progress bar. 
    ''' </summary>
    ''' <value>The value.</value>
    <DefaultValue(0L), Category("Behavior"), _
    RefreshProperties(RefreshProperties.All), _
    Description("The current value for the ProgressBar, in the range specified by the minimum and maximum properties.")> _
    Public Property Value() As Long
        Get
            Return clVal
        End Get
        Set(ByVal Value As Long)
            If Not (Value < clMin Or Value > clMax) Then
                clVal = Value
                Me.Invalidate()
            End If
        End Set
    End Property

    ''' <summary>
    ''' Gets or sets a value indicating whether to gradient whole visible bar or just the part of bar that is visible.
    ''' </summary>
    ''' <value>if <c>true</c> then gradient will be cauculated for length of visible bar; otherwise gradient will be calculate for the whole length the control and then applied to just the visible part.</value>
    <DefaultValue(False), Category("Appearance"), _
    RefreshProperties(RefreshProperties.All), _
    Description("True to display whole gradient in bar of current value.")> _
    Public Property GradientWholeBar() As Boolean
        Get
            Return Me.cbFill
        End Get
        Set(ByVal Value As Boolean)
            cbFill = Value
        End Set
    End Property

    ''' <summary>
    ''' Gets or sets a value indicating whether show percentage or not.
    ''' </summary>
    ''' <value>if <c>true</c>  then it will show percentage insted of text.</value>
    <DefaultValue(False), Category("Appearance"), _
    RefreshProperties(RefreshProperties.All), _
    Description("True to display percentage, False to display Text.")> _
    Public Property ShowPercentage() As Boolean
        Get
            Return cbPer
        End Get
        Set(ByVal Value As Boolean)
            cbPer = Value
        End Set
    End Property

    ''' <summary>
    ''' The text to display on the progress bar.
    ''' </summary>
    ''' <value>It will show text only if </value>
    <Browsable(True), Category("Appearance"), _
    RefreshProperties(RefreshProperties.All), _
    DefaultValue(""), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)> _
    Public Overrides Property Text() As String
        Get
            Return MyBase.Text
        End Get
        Set(ByVal Value As String)
            MyBase.Text = Value
            'Me.Invalidate()
        End Set
    End Property

    ''' <summary>
    ''' Gets or sets a value indicating whether to display text or percentage.
    ''' </summary>
    ''' <value>if <c>true</c> then it will display percentage if <see cref="ShowPercentage" /> is also set to true, if <b>ShowPercentage</b> is set tot <c>false</c> then it will display <see cref="Text" />; otherwise, it will not display any text on the progress bar.</value>
    <Browsable(True), Category("Appearance"), _
    RefreshProperties(RefreshProperties.All), _
    Description("True to display percentage or text, False to display nothing."), _
    DefaultValue(True)> _
    Public Property DisplayText() As Boolean
        Get
            Return cbText
        End Get
        Set(ByVal Value As Boolean)
            cbText = Value
        End Set
    End Property

    ''' <summary>
    ''' Gets or sets the text align.
    ''' </summary>
    ''' <value>The text align.</value>
    <Browsable(True), Category("Appearance"), _
    RefreshProperties(RefreshProperties.All), _
    Description("Determines the position of the text within progressbar."), _
    DefaultValue(GetType(ContentAlignment), "ContentAlignment.MiddleCenter")> _
    Public Property TextAlign() As ContentAlignment
        Get
            Return Me.ccaText
        End Get
        Set(ByVal Value As ContentAlignment)
            Me.ccaText = Value
        End Set
    End Property

    ''' <summary>
    ''' Gets or sets the alpha value of the progress bar.
    ''' </summary>
    ''' <value>The alpha color value.</value>
    <DefaultValue(255), Category("Appearance"), _
    RefreshProperties(RefreshProperties.All), _
    Description("Alpha value of colors.")> _
    Public Property Alpha() As Byte
        Get
            Return cbAlpha
        End Get
        Set(ByVal Value As Byte)
            cbAlpha = Value
        End Set
    End Property

    ''''' <PermissionSet><IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" /></PermissionSet>
    ''' <summary>
    ''' Gets or sets the foreground color of the control.
    ''' </summary>
    ''' <value></value>
    ''' <returns>The foreground <see cref="T:System.Drawing.Color"></see> of the control. The default is the value of the <see cref="P:System.Windows.Forms.Control.DefaultForeColor"></see> property.</returns>
    <DefaultValue(GetType(SystemColors), "ControlText"), _
    RefreshProperties(RefreshProperties.All), _
    Description("True to display percentage, False to display Text.")> _
    Public Overrides Property ForeColor() As Color
        Get
            Return MyBase.ForeColor
        End Get
        Set(ByVal Value As Color)
            MyBase.ForeColor = Value
        End Set
    End Property

    ''' <summary>
    ''' Gets or sets the starting <see cref="T:System.Drawing.Color"></see> of the bar.
    ''' </summary>
    ''' <value>The starting color of the progress bar.</value>
    <DefaultValue(GetType(Color), "Blue"), Category("Appearance"), _
    RefreshProperties(RefreshProperties.All), _
    Description("True to display percentage, False to display Text.")> _
    Public Property BarColor1() As Color
        Get
            Return ccolBar1
        End Get
        Set(ByVal Value As Color)
            ccolBar1 = Value
        End Set
    End Property

    ''' <summary>
    ''' Gets or sets the ending <see cref="T:System.Drawing.Color"></see> of the bar.
    ''' </summary>
    ''' <value>The ending color of the progress bar.</value>
    <DefaultValue(GetType(Color), "LimeGreen"), Category("Appearance"), _
    RefreshProperties(RefreshProperties.All), _
    Description("True to display percentage, False to display Text.")> _
    Public Property BarColor2() As Color
        Get
            Return ccolBar2
        End Get
        Set(ByVal Value As Color)
            ccolBar2 = Value
        End Set
    End Property

    ''' <summary>
    ''' Gets or sets the border style2. If <see cref="BorderStyle" /> is set to <c>None</c> then this border style will be applied.
    ''' </summary>
    ''' <value>The border style2.</value>
    <DefaultValue(GetType(System.Windows.Forms.Border3DStyle), "Adjust"), _
    RefreshProperties(RefreshProperties.All), Category("Appearance"), _
    Description("Inidicates whether or not control should have a custom border. Make sure BorderStyle property is set to None.")> _
    Public Overloads Property BorderStyle2() As System.Windows.Forms.Border3DStyle
        Get
            Return Me.csbsBorder
        End Get
        Set(ByVal Value As System.Windows.Forms.Border3DStyle)
            Me.csbsBorder = Value
        End Set
    End Property

    ''' <summary>
    ''' Gets or sets the gradient.
    ''' </summary>
    ''' <value>The gradient.</value>
    <DefaultValue(GetType(GradientEnum), "None"), Category("Appearance"), _
    RefreshProperties(RefreshProperties.All), _
    Description("Inidicates the orientation of the gradient fill of the progressbar. The orientation determines the starting and ending points of the gradient. For example, LinearGradientMode.ForwardDiagonal specifies that the starting point is the upper-left corner of the rectangle and the ending point is the lower-right corner of the rectangle.")> _
    Public Property Gradient() As GradientEnum
        Get
            Return Me.csgGrad
        End Get
        Set(ByVal Value As GradientEnum)
            Me.csgGrad = Value
        End Set
    End Property

    ''' <summary>
    ''' Gets or sets the gradient angle.
    ''' </summary>
    ''' <value>The gradient angle.</value>
    <DefaultValue(0), Category("Appearance"), _
    RefreshProperties(RefreshProperties.All), _
    Description("The angle, measured in degrees clockwise from the x-axis, of the gradient's orientation line.")> _
    Public Property GradientAngle() As Single
        Get
            Return Me.csAngle
        End Get
        Set(ByVal Value As Single)
            Me.csAngle = Value
        End Set
    End Property

    ''' <summary>
    ''' Gets or sets a value indicating whether angle is scaleable or not.
    ''' </summary>
    ''' <value>
    ''' if <c>true</c> then gradient angle of color is scalabel.
    ''' </value>
    <DefaultValue(True), Category("Appearance"), _
    RefreshProperties(RefreshProperties.All), _
    Description("Set to true to specify that the angle is affected by the transform associated with progressbar's Gradient; otherwise, false. ")> _
    Public Property IsAngleScaleable() As Boolean
        Get
            Return Me.cbAScale
        End Get
        Set(ByVal Value As Boolean)
            Me.cbAScale = Value
        End Set
    End Property

    ''' <summary>
    ''' Gets or sets the hatch style to overlay on the progress bar.
    ''' </summary>
    ''' <value>The hatch style.</value>
    <DefaultValue(GetType(HatchEnum), "None"), Category("Appearance"), _
    RefreshProperties(RefreshProperties.All), _
    Description("Set to true to specify that the angle is affected by the transform associated with progressbar's Gradient; otherwise, false. ")> _
    Public Property Hatch() As HatchEnum
        Get
            Return Me.cshHatch
        End Get
        Set(ByVal Value As HatchEnum)
            Me.cshHatch = Value
        End Set
    End Property
#End Region

#Region " Progressbar Methods "
    ''' <summary>
    ''' Advances the current position of the progress bar by the specified amount. 
    ''' </summary>
    ''' <param name="iStep">The amount by which to increment the progress bar's current position.</param>
    Public Sub Increment(ByVal iStep As Integer)
        Me.clVal += iStep
        If clVal > Me.clMax Then
            clVal = Me.clMax
        ElseIf clVal < Me.clMin Then
            clVal = Me.clMin
        End If
    End Sub

    ''' <summary>
    ''' Advances the current position of the progress bar by the amount of the <see cref="ProgressBar.Step" /> property.  
    ''' </summary>
    Public Sub PerformStep()
        Increment(Me.ciStep)
        Me.Invalidate()
    End Sub

    ''' <summary>
    ''' Copies all the properties from given Progress bar to the orher.
    ''' </summary>
    ''' <param name="mpbFrom">The progress bar from which to copy.</param>
    ''' <param name="mpbTo">The progress in which to copy.</param>
    ''' <param name="CopyValues">if set to <c>true</c> it will copy the values (Minimum, Maximum, Value, Step &amp; Text).</param>
    Public Shared Sub Copy(ByRef mpbFrom As ProgressBar, ByRef mpbTo As ProgressBar, Optional ByVal CopyValues As Boolean = False)
        With mpbTo
            If CopyValues Then
                .Maximum = mpbFrom.Maximum
                .Minimum = mpbFrom.Minimum
                .Value = mpbFrom.Value
                .Step = mpbFrom.Step
                .Text = mpbFrom.Text
            End If
            .Gradient = mpbFrom.Gradient
            .GradientAngle = mpbFrom.GradientAngle
            .GradientWholeBar = mpbFrom.GradientWholeBar
            .Hatch = mpbFrom.Hatch
            .Alpha = mpbFrom.Alpha
            .BackColor = mpbFrom.BackColor
            .ForeColor = mpbFrom.ForeColor
            .TextAlign = mpbFrom.TextAlign
            .Font = mpbFrom.Font
            .ShowPercentage = mpbFrom.ShowPercentage
            .DisplayText = mpbFrom.DisplayText
            .BarColor1 = mpbFrom.BarColor1
            .BarColor2 = mpbFrom.BarColor2
            .BorderStyle = mpbFrom.BorderStyle
            .IsAngleScaleable = mpbFrom.IsAngleScaleable
            .ShowPercentage = mpbFrom.ShowPercentage
        End With
    End Sub

#End Region

#Region " Paint The Bar "
    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        'MyBase.OnPaint(e)
        Dim b As Brush
        Dim tb As Brush = New SolidBrush(Me.ForeColor)
        Dim sf As StringFormat
        Dim rf As RectangleF
        Dim per, l, t, w, h As Single
        Dim cSt, cEd As Color

        If Alpha = 0 Then
            cSt = Me.BarColor1
            cEd = Me.BarColor2
        Else
            cSt = Color.FromArgb(Me.cbAlpha, ccolBar1)
            cEd = Color.FromArgb(Me.cbAlpha, ccolBar2)
        End If


        e.Graphics.Clear(Me.BackColor)
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias
        e.Graphics.TextRenderingHint = Drawing.Text.TextRenderingHint.ClearTypeGridFit

        sf = New StringFormat(StringFormatFlags.NoWrap Or StringFormatFlags.NoClip)
        Select Case Me.ccaText
            Case ContentAlignment.BottomCenter
                sf.Alignment = StringAlignment.Center
                sf.LineAlignment = StringAlignment.Far
            Case ContentAlignment.BottomLeft
                sf.Alignment = StringAlignment.Near
                sf.LineAlignment = StringAlignment.Far
            Case ContentAlignment.BottomRight
                sf.Alignment = StringAlignment.Far
                sf.LineAlignment = StringAlignment.Far
            Case ContentAlignment.MiddleCenter
                sf.Alignment = StringAlignment.Center
                sf.LineAlignment = StringAlignment.Center
            Case ContentAlignment.MiddleLeft
                sf.Alignment = StringAlignment.Near
                sf.LineAlignment = StringAlignment.Center
            Case ContentAlignment.MiddleRight
                sf.Alignment = StringAlignment.Far
                sf.LineAlignment = StringAlignment.Center
            Case ContentAlignment.TopCenter
                sf.Alignment = StringAlignment.Center
                sf.LineAlignment = StringAlignment.Near
            Case ContentAlignment.TopLeft
                sf.Alignment = StringAlignment.Near
                sf.LineAlignment = StringAlignment.Near
            Case ContentAlignment.TopRight
                sf.Alignment = StringAlignment.Far
                sf.LineAlignment = StringAlignment.Near
        End Select

        If Me.Maximum = 0 OrElse (Me.Maximum - Me.Minimum) = 0 Then
            per = 0
        Else
            per = CSng((Me.Value - Me.Minimum) / (Me.Maximum - Me.Minimum))
        End If
        Select Case Me.BorderStyle
            Case Windows.Forms.BorderStyle.None
                Select Case Me.csbsBorder
                    Case Border3DStyle.Bump, Border3DStyle.Etched, Border3DStyle.Flat, Border3DStyle.Raised, Border3DStyle.Sunken
                        l = 2
                        t = 2
                        w = (Me.Width - 5)
                        h = (Me.Height - 5)
                    Case Border3DStyle.RaisedInner, Border3DStyle.RaisedOuter, Border3DStyle.SunkenInner, Border3DStyle.SunkenOuter
                        l = 1
                        t = 1
                        w = (Me.Width - 3)
                        h = (Me.Height - 3)
                    Case Border3DStyle.Adjust
                        l = 0
                        t = 0
                        w = Me.Width - 1
                        h = Me.Height - 1
                    Case Else
                        l = 0
                        t = 0
                        w = Me.Width
                        h = Me.Height
                End Select
            Case Windows.Forms.BorderStyle.FixedSingle
                l = 0
                t = 0
                w = Me.Width - 3
                h = Me.Height - 3
            Case Windows.Forms.BorderStyle.Fixed3D
                l = 0
                t = 0
                w = Me.Width - 5
                h = Me.Height - 5
            Case Else
                l = 0
                t = 0
                w = Me.Width
                h = Me.Height
        End Select
        If Me.cbFill Then
            rf = New RectangleF(0, 0, w * per, h)
        Else
            rf = New RectangleF(0, 0, w, h)
        End If
        If rf.Width = 0 Then rf.Width = 0.000001F
        Select Case Me.csgGrad
            Case GradientEnum.Horizontal
                b = New Drawing2D.LinearGradientBrush(rf, cSt, cEd, Drawing2D.LinearGradientMode.Horizontal)
            Case GradientEnum.Vertical
                b = New Drawing2D.LinearGradientBrush(rf, cSt, cEd, Drawing2D.LinearGradientMode.Vertical)
            Case GradientEnum.ForwardDiagonal
                b = New Drawing2D.LinearGradientBrush(rf, cSt, cEd, Drawing2D.LinearGradientMode.ForwardDiagonal)
            Case GradientEnum.BackwardDiagonal
                b = New Drawing2D.LinearGradientBrush(rf, cSt, cEd, Drawing2D.LinearGradientMode.BackwardDiagonal)
            Case GradientEnum.CustomAngle
                b = New Drawing2D.LinearGradientBrush(rf, cSt, cEd, Me.csAngle, Me.cbAScale)
            Case GradientEnum.Continuous
                cGrd.StartColor = cSt
                cGrd.EndColor = cEd
                b = New SolidBrush(cGrd.ColorAt(per))
            Case GradientEnum.Rainbow
                Dim dp As Decimal = 1D / 7
                Dim cb As Drawing2D.ColorBlend
                Dim br As Drawing2D.LinearGradientBrush
                Dim a As Byte = CByte(IIf(Alpha = 0, 255, Alpha).ToString)

                br = New Drawing2D.LinearGradientBrush(rf, Color.FromArgb(a, Color.SkyBlue), Color.FromArgb(a, Color.SkyBlue), Me.csAngle, Me.cbAScale)
                'br = New Drawing2D.LinearGradientBrush(rf, Color.FromArgb(a, Color.SkyBlue), Color.FromArgb(a, Color.SkyBlue), Drawing2D.LinearGradientMode.Horizontal)
                cb = New Drawing2D.ColorBlend(8)
                cb.Colors = New Color() {Color.FromArgb(a, Color.Red), Color.FromArgb(a, Color.Orange), _
                  Color.FromArgb(a, Color.Yellow), Color.FromArgb(a, Color.Green), _
                  Color.FromArgb(a, Color.Blue), Color.FromArgb(a, Color.Indigo), _
                  Color.FromArgb(a, Color.Violet), Color.FromArgb(a, Color.Red)}
                cb.Positions = New Single() {0, dp, dp * 2, dp * 3, dp * 4, dp * 5, dp * 6, 1}
                br.InterpolationColors = cb
                b = br
            Case Else           'GradientEnum.None
                b = New SolidBrush(cSt)
        End Select
        If Not Me.cbFill Then
            rf = New RectangleF(l, t, CSng(IIf((w * per) > rf.Width, rf.Width, (w * per)).ToString), h)
        End If
        e.Graphics.FillRectangle(b, rf)
        b.Dispose()
        rf = New RectangleF(l, t, w, h)
        If Me.cshHatch <> HatchEnum.None Then
            b = New Drawing2D.HatchBrush(CType(Me.cshHatch, System.Drawing.Drawing2D.HatchStyle), Me.BackColor, Color.Transparent)
            e.Graphics.FillRectangle(b, rf)
            b.Dispose()
        End If

        If Me.DisplayText Then
            If Me.ShowPercentage Then
                e.Graphics.DrawString(String.Format("({0:0.00%})", per), Me.Font, tb, rf, sf)
            Else
                e.Graphics.DrawString(Me.Text, Me.Font, tb, rf, sf)
            End If
        End If
        tb.Dispose()
        sf.Dispose()
        If Me.BorderStyle = Windows.Forms.BorderStyle.None Then
            ControlPaint.DrawBorder3D(e.Graphics, 0, 0, Me.Width, Me.Height, Me.csbsBorder)
        End If

    End Sub

#End Region

#Region " Control  Hide Properties "

    <Browsable(False), DesignOnly(True), EditorBrowsable(EditorBrowsableState.Never)> _
    Public Shadows ReadOnly Property AllowDrop() As Boolean
        Get
            Return MyBase.AllowDrop
        End Get
    End Property


    <Browsable(False), DesignOnly(True), EditorBrowsable(EditorBrowsableState.Never)> _
    Public Shadows ReadOnly Property AutoScaleDimensions() As System.Drawing.SizeF
        Get
            Return MyBase.AutoScaleDimensions
        End Get
    End Property

    <Browsable(False), DesignOnly(True), EditorBrowsable(EditorBrowsableState.Never)> _
    Public Shadows ReadOnly Property AutoScaleMode() As System.Windows.Forms.AutoScaleMode
        Get
            Return MyBase.AutoScaleMode
        End Get
    End Property

    <Browsable(False), DesignOnly(True), EditorBrowsable(EditorBrowsableState.Never)> _
    Public Shadows ReadOnly Property AutoScroll() As Boolean
        Get
            Return MyBase.AutoScroll
        End Get
    End Property

    <Browsable(False), DesignOnly(True), EditorBrowsable(EditorBrowsableState.Never)> _
    Public Shadows ReadOnly Property AutoScrollMargin() As Drawing.Size
        Get
            Return MyBase.AutoScrollMargin
        End Get
    End Property

    <Browsable(False), DesignOnly(True), EditorBrowsable(EditorBrowsableState.Never)> _
    Public Shadows ReadOnly Property AutoScrollMinSize() As Drawing.Size
        Get
            Return MyBase.AutoScrollMinSize
        End Get
    End Property

    <Browsable(False), DesignOnly(True), EditorBrowsable(EditorBrowsableState.Never)> _
    Public Shadows ReadOnly Property AutoScrollOffset() As System.Drawing.Point
        Get
            Return MyBase.AutoScrollOffset
        End Get
    End Property

    <Browsable(False), DesignOnly(True), EditorBrowsable(EditorBrowsableState.Never)> _
    Public Shadows ReadOnly Property AutoScrollPosition() As System.Drawing.Point
        Get
            Return MyBase.AutoScrollPosition
        End Get
    End Property

    <Browsable(False), DesignOnly(True), EditorBrowsable(EditorBrowsableState.Never)> _
    Public Shadows ReadOnly Property AutoSize() As Boolean
        Get
            Return MyBase.AutoSize
        End Get
    End Property

    <Browsable(False), DesignOnly(True), EditorBrowsable(EditorBrowsableState.Never)> _
    Public Shadows ReadOnly Property AutoSizeMode() As System.Windows.Forms.AutoSizeMode
        Get
            Return MyBase.AutoSizeMode
        End Get
    End Property

    <Browsable(False), DesignOnly(True), EditorBrowsable(EditorBrowsableState.Never)> _
    Public Shadows ReadOnly Property AutoValidate() As System.Windows.Forms.AutoValidate
        Get
            Return MyBase.AutoValidate
        End Get
    End Property

    <Browsable(False), DesignOnly(True), EditorBrowsable(EditorBrowsableState.Never)> _
    Public Overloads ReadOnly Property CausesValidation() As Boolean
        Get
            Return False
        End Get
    End Property

    <Browsable(False), DesignOnly(True), EditorBrowsable(EditorBrowsableState.Never)> _
    Public Shadows ReadOnly Property CurrentAutoScaleDimensions() As System.Drawing.SizeF
        Get
            Return MyBase.CurrentAutoScaleDimensions
        End Get
    End Property

    <Browsable(False), DesignOnly(True), EditorBrowsable(EditorBrowsableState.Never)> _
    Public Shadows ReadOnly Property HorizontalScroll() As System.Windows.Forms.HScrollProperties
        Get
            Return MyBase.HorizontalScroll
        End Get
    End Property

    <Browsable(False), DesignOnly(True), EditorBrowsable(EditorBrowsableState.Never)> _
    Public Overloads ReadOnly Property ImeMode() As System.Windows.Forms.ImeMode
        Get
            Return Windows.Forms.ImeMode.NoControl
        End Get
    End Property

    <EditorBrowsable(EditorBrowsableState.Never)> _
    Public Overloads Sub PerformAutoScale()
        MyBase.PerformAutoScale()
    End Sub

    <Browsable(False), DesignOnly(True), EditorBrowsable(EditorBrowsableState.Never)> _
    Public Overloads Sub SetAutoScrollMargin(ByVal x As Integer, ByVal y As Integer)
        MyBase.SetAutoScrollMargin(x, y)
    End Sub

    <Browsable(False), DesignOnly(True), EditorBrowsable(EditorBrowsableState.Never)> _
    Public Overloads ReadOnly Property TabStop() As Boolean
        Get
            Return False
        End Get
    End Property

    <Browsable(False), DesignOnly(True), EditorBrowsable(EditorBrowsableState.Never)> _
    Public Shadows ReadOnly Property VerticalScroll() As System.Windows.Forms.VScrollProperties
        Get
            Return MyBase.VerticalScroll
        End Get
    End Property
#End Region

End Class

Friend Class ProgressBarDesigner
    Inherits System.Windows.Forms.Design.ControlDesigner

    Private lists As DesignerActionListCollection

    Public Sub New()
        MyBase.New()
    End Sub

    'Use pull model to populate smart tag menu.
    Public Overrides ReadOnly Property ActionLists() _
    As DesignerActionListCollection
        Get
            If lists Is Nothing Then
                lists = New DesignerActionListCollection()
                lists.Add( _
                New ProgressBarActionList(Me.Component))
            End If
            Return lists
        End Get
    End Property

End Class

'///////////////////////////////////////////////////////////////
'DesignerActionList-derived class defines smart tag entries and
' resultant actions.
'///////////////////////////////////////////////////////////////
Friend Class ProgressBarActionList
    Inherits System.ComponentModel.Design.DesignerActionList

    Private l_uct As ProgressBar

    Private designerActionUISvc As DesignerActionUIService = Nothing

    'The constructor associates the control 
    'with the smart tag list.
    Public Sub New(ByVal component As IComponent)

        MyBase.New(component)
        Me.l_uct = DirectCast(component, ProgressBar)

        ' Cache a reference to DesignerActionUIService, so the
        ' DesigneractionList can be refreshed.
        Me.designerActionUISvc = _
        CType(GetService(GetType(DesignerActionUIService)), _
        DesignerActionUIService)

    End Sub

    'Helper method to retrieve control properties. Use of 
    ' GetProperties enables undo and menu updates to work properly.
    Private Function GetPropertyByName(ByVal propName As String) _
    As PropertyDescriptor
        Dim prop As PropertyDescriptor
        prop = TypeDescriptor.GetProperties(l_uct)(propName)
        If prop Is Nothing Then
            Throw New ArgumentException( _
            "Matching mitProgressBar property not found!", propName)
        Else
            Return prop
        End If
    End Function

    'Properties that are targets of DesignerActionPropertyItem entries.
    Public Property Alpha() As Byte
        Get
            Return l_uct.Alpha
        End Get
        Set(ByVal value As Byte)
            GetPropertyByName("Alpha").SetValue(l_uct, value)
        End Set
    End Property

    Public Property BackColor() As System.Drawing.Color
        Get
            Return l_uct.BackColor
        End Get
        Set(ByVal value As System.Drawing.Color)
            GetPropertyByName("BackColor").SetValue(l_uct, value)
        End Set
    End Property

    Public Property BarColor1() As System.Drawing.Color
        Get
            Return l_uct.BarColor1
        End Get
        Set(ByVal value As System.Drawing.Color)
            GetPropertyByName("BarColor1").SetValue(l_uct, value)
        End Set
    End Property

    Public Property BarColor2() As System.Drawing.Color
        Get
            Return l_uct.BarColor2
        End Get
        Set(ByVal value As System.Drawing.Color)
            GetPropertyByName("BarColor2").SetValue(l_uct, value)
        End Set
    End Property

    Public Property BorderStyle() As System.Windows.Forms.BorderStyle
        Get
            Return l_uct.BorderStyle
        End Get
        Set(ByVal value As System.Windows.Forms.BorderStyle)
            GetPropertyByName("BorderStyle").SetValue(l_uct, value)

            Me.designerActionUISvc.Refresh(Me.Component)
        End Set
    End Property

    Public Property BorderStyle2() As System.Windows.Forms.Border3DStyle
        Get
            Return l_uct.BorderStyle2
        End Get
        Set(ByVal value As System.Windows.Forms.Border3DStyle)
            GetPropertyByName("BorderStyle2").SetValue(l_uct, value)
        End Set
    End Property

    Public Property DisplayText() As Boolean
        Get
            Return l_uct.DisplayText
        End Get
        Set(ByVal value As Boolean)
            GetPropertyByName("DisplayText").SetValue(l_uct, value)
            Me.designerActionUISvc.Refresh(Me.Component)
        End Set
    End Property

    Public Property ForeColor() As System.Drawing.Color
        Get
            Return l_uct.ForeColor
        End Get
        Set(ByVal value As System.Drawing.Color)
            GetPropertyByName("ForeColor").SetValue(l_uct, value)
        End Set
    End Property

    Public Property Gradient() As GradientEnum
        Get
            Return l_uct.Gradient
        End Get
        Set(ByVal value As GradientEnum)
            GetPropertyByName("Gradient").SetValue(l_uct, value)

            Me.designerActionUISvc.Refresh(Me.Component)
        End Set
    End Property

    Public Property GradientAngle() As Single
        Get
            Return l_uct.GradientAngle
        End Get
        Set(ByVal value As Single)
            GetPropertyByName("GradientAngle").SetValue(l_uct, value)
        End Set
    End Property

    Public Property GradientWholeBar() As Boolean
        Get
            Return l_uct.GradientWholeBar
        End Get
        Set(ByVal value As Boolean)
            GetPropertyByName("GradientWholeBar").SetValue(l_uct, value)
        End Set
    End Property

    Public Property Hatch() As HatchEnum
        Get
            Return l_uct.Hatch
        End Get
        Set(ByVal value As HatchEnum)
            GetPropertyByName("Hatch").SetValue(l_uct, value)
        End Set
    End Property

    Public Property IsAngleScaleable() As Boolean
        Get
            Return l_uct.IsAngleScaleable
        End Get
        Set(ByVal value As Boolean)
            GetPropertyByName("IsAngleScaleable").SetValue(l_uct, value)
        End Set
    End Property

    Public Property Maximum() As Long
        Get
            Return l_uct.Maximum
        End Get
        Set(ByVal value As Long)
            GetPropertyByName("Maximum").SetValue(l_uct, value)
        End Set
    End Property

    Public Property Minimum() As Long
        Get
            Return l_uct.Minimum
        End Get
        Set(ByVal value As Long)
            GetPropertyByName("Minimum").SetValue(l_uct, value)
        End Set
    End Property

    Public Property Value() As Long
        Get
            Return l_uct.Value
        End Get
        Set(ByVal value As Long)
            GetPropertyByName("Value").SetValue(l_uct, value)
        End Set
    End Property

    Public Property ShowPercentage() As Boolean
        Get
            Return l_uct.ShowPercentage
        End Get
        Set(ByVal value As Boolean)
            GetPropertyByName("ShowPercentage").SetValue(l_uct, value)
        End Set
    End Property

    Public Property [Step]() As Integer
        Get
            Return l_uct.Step
        End Get
        Set(ByVal value As Integer)
            GetPropertyByName("Step").SetValue(l_uct, value)
        End Set
    End Property

    Public Property TextAlign() As System.Drawing.ContentAlignment
        Get
            Return l_uct.TextAlign
        End Get
        Set(ByVal value As System.Drawing.ContentAlignment)
            GetPropertyByName("TextAlign").SetValue(l_uct, value)
        End Set
    End Property

    'Method that is target of a DesignerActionMethodItem
    Public Sub Preview()
        Dim l_pval As Long
        Dim l_val As Long

        l_pval = l_uct.Value

        l_val = l_uct.Minimum
        Do While l_val <= l_uct.Maximum
            l_uct.Value = l_val
            l_uct.Refresh()
            Application.DoEvents()
            System.Threading.Thread.Sleep(30)
            l_val += l_uct.Step
        Loop
        l_val -= l_uct.Step
        If l_val < l_uct.Maximum Then
            l_uct.Value = l_uct.Maximum
            l_uct.Refresh()
            Application.DoEvents()
            System.Threading.Thread.Sleep(30)
        End If

        l_uct.Value = l_pval
    End Sub

    'Method that is target of a DesignerActionMethodItem
    Public Sub PreviewRev()
        Dim l_pval As Long
        Dim l_val As Long

        l_pval = l_uct.Value

        l_val = l_uct.Maximum
        Do While l_val >= l_uct.Minimum
            l_uct.Value = l_val
            l_uct.Refresh()
            Application.DoEvents()
            System.Threading.Thread.Sleep(30)
            l_val -= l_uct.Step
        Loop
        l_val += l_uct.Step
        If l_val > l_uct.Minimum Then
            l_uct.Value = l_uct.Minimum
            l_uct.Refresh()
            Application.DoEvents()
            System.Threading.Thread.Sleep(30)
        End If

        l_uct.Value = l_pval
    End Sub

    'Implementation of this virtual method creates smart tag  
    ' items, associates their targets, and collects into list.
    Public Overrides Function GetSortedActionItems() As DesignerActionItemCollection
        Dim items As New DesignerActionItemCollection()

        'Define static section header entries.
        items.Add(New DesignerActionHeaderItem("Appearance"))
        items.Add(New DesignerActionHeaderItem("Gradient"))
        items.Add(New DesignerActionHeaderItem("Color"))
        items.Add(New DesignerActionHeaderItem("Behavior"))
        items.Add(New DesignerActionHeaderItem("Preview"))

        items.Add(New DesignerActionPropertyItem( _
         "Alpha", "Aplha Blend", "Appearance", "How much bar should blend with background"))

        items.Add(New DesignerActionPropertyItem( _
         "BackColor", "Background Color", "Appearance", "Background Color"))

        items.Add(New DesignerActionPropertyItem( _
         "BorderStyle", "Border Style", "Appearance", "Border Style of this control"))

        If BorderStyle = Windows.Forms.BorderStyle.None Then
            items.Add(New DesignerActionPropertyItem( _
             "BorderStyle2", "Border Style-2", "Appearance", "3D Border Style of this control"))
        End If

        items.Add(New DesignerActionPropertyItem( _
         "TextAlign", "Text Align", "Appearance", "Text Alignemnt"))

        items.Add(New DesignerActionPropertyItem( _
         "DisplayText", "Display Text", "Appearance", "Display Text on progress bar"))

        If DisplayText Then
            items.Add(New DesignerActionPropertyItem( _
             "ShowPercentage", "Show Percentage", "Appearance", "Show text or percentage"))
        End If

        If Not (Gradient = GradientEnum.None OrElse Gradient = GradientEnum.Rainbow) Then
            items.Add(New DesignerActionPropertyItem( _
             "BarColor1", "Bar Starting Color", "Color", "Starting color of progress bar"))

            items.Add(New DesignerActionPropertyItem( _
             "BarColor2", "Bar Ending Color", "Color", "Ending color of progress bar"))
        End If

        items.Add(New DesignerActionPropertyItem( _
         "ForeColor", "Text Color", "Color", "Color of text to display"))

        items.Add(New DesignerActionPropertyItem( _
         "Gradient", "Gradient", "Gradient", "Gradient Style"))

        If Gradient = GradientEnum.CustomAngle OrElse Gradient = GradientEnum.Rainbow Then
            items.Add(New DesignerActionPropertyItem( _
             "GradientAngle", "Gradient Angle", "Gradient", "Angle of the gradient"))

            items.Add(New DesignerActionPropertyItem( _
             "IsAngleScaleable", "Is Angle Scalable", "Gradient", "Is angle scalable?"))
        End If

        If Gradient <> GradientEnum.None Then
            items.Add(New DesignerActionPropertyItem( _
             "GradientWholeBar", "Gradient Whole Bar", "Gradient", "Shoud gradient the displayed bar as a whole bar?"))
        End If

        items.Add(New DesignerActionPropertyItem( _
         "Hatch", "Hatch Overlay", "Gradient", "Hatch style to overlay on bar"))

        items.Add(New DesignerActionPropertyItem( _
         "Maximum", "Maximum", "Behavior", "Maximum Value"))

        items.Add(New DesignerActionPropertyItem( _
         "Minimum", "Minimum", "Behavior", "Minimum Value"))

        items.Add(New DesignerActionPropertyItem( _
         "Step", "Step", "Behavior", "Step Value"))

        'This next method item is also added to the context menu (as a designer verb).
        items.Add( _
        New DesignerActionMethodItem( _
        Me, _
        "Preview", _
        "Preview...", _
        "Preview", _
        "See the progress bar in action.", _
        True))

        items.Add( _
        New DesignerActionMethodItem( _
        Me, _
        "PreviewRev", _
        "Preview In Reveres...", _
        "Preview", _
        "See the progress bar in action in reveres.", _
        True))

        Return items
    End Function

End Class
