1

I'm trying to change the fore colour of a progress bar in vb.net and there is a way to do it by disabling XP visual styles but I don't want to do it that way because by doing that it makes the application look unclean so I've been trying to find out a way to make it work without disabling that option and I have found one but it only seems to work when the colour is set to green, if it is set to red or yellow the progress bar has no colour. This is the code I have found that doesn't work:

Public Class Form1

 Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Integer,
          ByVal wMsg As Integer, ByVal wParam As Integer, 
          ByVal lParam As Integer) As Integer

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
       SendMessage(ProgressBar1.Handle, 1040, 2, 0)
       ProgressBar1.Increment(10)
       End Sub
  End Class

That doesn't seem to work at all so I was wondering is there is another way to do it without disabling XP visual styles?

Ňɏssa Pøngjǣrdenlarp
  • 38,411
  • 12
  • 59
  • 178
user2387537
  • 361
  • 3
  • 9
  • 17

1 Answers1

2

You could create your own custom progress bar by inheriting from the ProgressBar class:

Imports System.Drawing.Drawing2D
Namespace WindowsFormsApplication1
    Class ProgressBarColor
        Inherits System.Windows.Forms.ProgressBar
        Private _Color As Color
        Private brush As New System.Drawing.Drawing2D.LinearGradientBrush(New Rectangle(1, 1, 1, 1), Color.FloralWhite, Color.Firebrick, LinearGradientMode.Vertical)
        Private m_rec As Rectangle
        Private draw As Boolean

        Private indraw As Boolean = True
        Public Sub New()
            MyBase.New()
            Me.SetStyle(System.Windows.Forms.ControlStyles.UserPaint, True)
            _Color = Color.Red
            m_rec = New Rectangle(1, 1, 1, 1)
            draw = False
        End Sub

        <Category("Appearance"), Description("The Color of the progress bar")> _
        <Browsable(True)> _
        Public Property Color() As Color
            Get
                Return _Color
            End Get
            Set
                _Color = value
            End Set
        End Property


        <Category("Behavior"), Description("Whether or not the progress bar should draw itself when the value hasn't changed")> _
        <Browsable(True)> _
        Public Property DrawEveryFrame() As Boolean
            Get
                Return draw
            End Get
            Set
                draw = value
            End Set
        End Property

        Public Property Rec() As Rectangle
            Get
                Return m_rec
            End Get
            Set
                If value.Height = 0 Then
                    value.Height = 1
                End If
                If value.Width = 0 Then
                    value.Width = 1
                End If
                m_rec = value
                brush = New LinearGradientBrush(value, _Color, Color.FromArgb(_Color.R / 2, _Color.G / 2, _Color.B / 2), LinearGradientMode.Vertical)
            End Set
        End Property

        Protected Overrides Sub OnPaintBackground(pevent As PaintEventArgs)

        End Sub

        Protected Overrides Sub OnPaint(e As System.Windows.Forms.PaintEventArgs)
            Dim width As Integer = 0
            If Value <> 0 Then
                width = (e.ClipRectangle.Width * Value \ Maximum) - 4
            End If
            If (m_rec.X <> e.ClipRectangle.X OrElse m_rec.Y <> e.ClipRectangle.Y OrElse m_rec.Width <> width OrElse m_rec.Height <> e.ClipRectangle.Height - 4) OrElse draw OrElse indraw Then
                indraw = False
                Rec = New Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y, Me.Size.Width, Me.Size.Height)
                If m_rec.Height = 0 Then
                    m_rec.Height = 1
                End If
                If ProgressBarRenderer.IsSupported Then
                    ProgressBarRenderer.DrawHorizontalBar(e.Graphics, e.ClipRectangle)
                End If
                m_rec.Width = CInt(m_rec.Width * (CDbl(Value) / Maximum)) - 4
                m_rec.Height -= 4
                If m_rec.Width = 0 Then
                    m_rec.Width = 1
                End If
                e.Graphics.FillRectangle(brush, 2, 2, m_rec.Width, m_rec.Height)
                MyBase.OnPaint(e)
            End If
        End Sub

    End Class
End Namespace

This will create a custom control in the toolbox that you should be able to add at design time. This is just to get you started. Hopefully it will help. (Note, if the bar is flickering with DrawEveryFrame set to false, you may need to change the LinearGradientBrush to a standard System.Drawing.Brush; or, call ProgressBarColor1.Update() from a timer or mousemove event handler).

davidsbro
  • 2,761
  • 4
  • 23
  • 33