How to change the color of progressbar in C# .NET 3.5?

C#.NetWinforms.Net 3.5

C# Problem Overview


I'd like to do two things on my progress bar.

  1. Change the green colour to red.
  2. Remove the blocks and make it in one color.

Any information about those two things I wonder how to accomplish will be greatfuly appreaciated!

Thanks.

C# Solutions


Solution 1 - C#

OK, it took me a while to read all the answers and links. Here's what I got out of them:

Sample Results

The accepted answer disables visual styles, it does allow you to set the color to anything you want, but the result looks plain:

enter image description here

Using the following method, you can get something like this instead:

enter image description here

How To

First, include this if you haven't: using System.Runtime.InteropServices;

Second, you can either create this new class, or put its code into an existing static non-generic class:

public static class ModifyProgressBarColor
{
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
    static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr w, IntPtr l);
    public static void SetState(this ProgressBar pBar, int state)
    {
        SendMessage(pBar.Handle, 1040, (IntPtr)state, IntPtr.Zero);
    }
}

Now, to use it, simply call:

progressBar1.SetState(2);

Note the second parameter in SetState, 1 = normal (green); 2 = error (red); 3 = warning (yellow).

Hope it helps!

Solution 2 - C#

Since the previous answers don't appear to work in with Visual Styles. You'll probably need to create your own class or extend the progress bar:

public class NewProgressBar : ProgressBar
{
    public NewProgressBar()
    {
        this.SetStyle(ControlStyles.UserPaint, true);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        Rectangle rec = e.ClipRectangle;

        rec.Width = (int)(rec.Width * ((double)Value / Maximum)) - 4;
        if(ProgressBarRenderer.IsSupported)
           ProgressBarRenderer.DrawHorizontalBar(e.Graphics, e.ClipRectangle);
        rec.Height = rec.Height - 4;
        e.Graphics.FillRectangle(Brushes.Red, 2, 2, rec.Width, rec.Height);
    }
}

EDIT: Updated code to make the progress bar use the visual style for the background

Solution 3 - C#

This is a flicker-free version of the most accepted code that you can find as answers to this question. All credit to the posters of those fatastic answers. Thanks Dusty, Chris, Matt, and Josh!

Like "Fueled"'s request in one of the comments, I also needed a version that behaved a bit more... professionaly. This code maintains styles as in previous code, but adds an offscreen image render and graphics buffering (and disposes the graphics object properly).

Result: all the good, and no flicker. :)

public class NewProgressBar : ProgressBar
{
	public NewProgressBar()
	{
		this.SetStyle(ControlStyles.UserPaint, true);
    }

    protected override void OnPaintBackground(PaintEventArgs pevent)
    {
		// None... Helps control the flicker.
    }

	protected override void OnPaint(PaintEventArgs e)
	{
		const int inset = 2; // A single inset value to control teh sizing of the inner rect.

		using (Image offscreenImage = new Bitmap(this.Width, this.Height))
		{
			using (Graphics offscreen = Graphics.FromImage(offscreenImage))
			{
				Rectangle rect = new Rectangle(0, 0, this.Width, this.Height);

				if (ProgressBarRenderer.IsSupported)
					ProgressBarRenderer.DrawHorizontalBar(offscreen, rect);

				rect.Inflate(new Size(-inset, -inset)); // Deflate inner rect.
				rect.Width = (int)(rect.Width * ((double)this.Value / this.Maximum));
				if (rect.Width == 0) rect.Width = 1; // Can't draw rec with width of 0.

				LinearGradientBrush brush = new LinearGradientBrush(rect, this.BackColor, this.ForeColor, LinearGradientMode.Vertical);
				offscreen.FillRectangle(brush, inset, inset, rect.Width, rect.Height);

				e.Graphics.DrawImage(offscreenImage, 0, 0);
			}
		}
	}
}

Solution 4 - C#

In the designer, you just need to set the ForeColor property to whatever color you'd like. In the case of Red, there's a predefined color for it.

To do it in code (C#) do this:

pgs.ForeColor = Color.Red;

Edit: Oh yeah, also set the Style to continuous. In code, like this:

pgs.Style = System.Windows.Forms.ProgressBarStyle.Continuous;

Another Edit: You'll also need to remove the line that reads Application.EnableVisualStyles() from your Program.cs (or similar). If you can't do this because you want the rest of the application to have visual styles, then I'd suggest painting the control yourself or moving on to WPF since this kind of thing is easy with WPF. You can find a tutorial on owner drawing a progress bar on codeplex

Solution 5 - C#

Using Matt Blaine and Chris Persichetti's answers I've created a progress bar that looks a bit nicer while allowing infinite color choice (basically I changed one line in Matt's solution):

ProgressBarEx:

using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace QuantumConcepts.Common.Forms.UI.Controls
{
    public class ProgressBarEx : ProgressBar
    {
        public ProgressBarEx()
        {
            this.SetStyle(ControlStyles.UserPaint, true);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            LinearGradientBrush brush = null;
            Rectangle rec = new Rectangle(0, 0, this.Width, this.Height);
            double scaleFactor = (((double)Value - (double)Minimum) / ((double)Maximum - (double)Minimum));

            if (ProgressBarRenderer.IsSupported)
                ProgressBarRenderer.DrawHorizontalBar(e.Graphics, rec);

            rec.Width = (int)((rec.Width * scaleFactor) - 4);
            rec.Height -= 4;
            brush = new LinearGradientBrush(rec, this.ForeColor, this.BackColor, LinearGradientMode.Vertical);
            e.Graphics.FillRectangle(brush, 2, 2, rec.Width, rec.Height);
        }
    }
}

Usage:

progressBar.ForeColor = Color.FromArgb(255, 0, 0);
progressBar.BackColor = Color.FromArgb(150, 0, 0);

Results
You can use any gradient you like!

Download
https://skydrive.live.com/?cid=0EDE5D21BDC5F270&id=EDE5D21BDC5F270%21160&sc=documents#

Solution 6 - C#

Modificaton to dustyburwell's answer. (I don't have enough rep to edit it myself.) Like his answer, it works with "Visual Styles" enabled. You can just set the progressbar's ForeColor property in whatever form's design view.

using System;
using System.Windows.Forms;
using System.Drawing;

public class ProgressBarEx : ProgressBar
{
    private SolidBrush brush = null;

    public ProgressBarEx()
    {
        this.SetStyle(ControlStyles.UserPaint, true);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        if (brush == null || brush.Color != this.ForeColor)
            brush = new SolidBrush(this.ForeColor);

        Rectangle rec = new Rectangle(0, 0, this.Width, this.Height);
        if (ProgressBarRenderer.IsSupported)
            ProgressBarRenderer.DrawHorizontalBar(e.Graphics, rec);
        rec.Width = (int)(rec.Width * ((double)Value / Maximum)) - 4;
        rec.Height = rec.Height - 4;
        e.Graphics.FillRectangle(brush, 2, 2, rec.Width, rec.Height);
    }
}

Solution 7 - C#

I just put this into a static class.

  const int WM_USER = 0x400;
  const int PBM_SETSTATE = WM_USER + 16;
  const int PBM_GETSTATE = WM_USER + 17;

  [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
  static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

  public enum ProgressBarStateEnum : int
  {
   Normal = 1,
   Error = 2,
   Paused = 3,
  }

  public static ProgressBarStateEnum GetState(this ProgressBar pBar)
  {
   return (ProgressBarStateEnum)(int)SendMessage(pBar.Handle, PBM_GETSTATE, IntPtr.Zero, IntPtr.Zero);
  }

  public static void SetState(this ProgressBar pBar, ProgressBarStateEnum state)
  {
   SendMessage(pBar.Handle, PBM_SETSTATE, (IntPtr)state, IntPtr.Zero);
  } 

Hope it helps,

Marc

Solution 8 - C#

Usually the progress bar is either themed or honors the user's color preferences. So for changing the color you either need to turn off visual styles and set ForeColor or draw the control yourself.

As for the continuous style instead of blocks you can set the Style property:

pBar.Style = ProgressBarStyle.Continuous;

Solution 9 - C#

EDIT

By the sounds of things you're using the XP Theme which has the green block based prog-bar. Try flipping your UI Style to Windows Classic and test again, but you may need to implement your own OnPaint event to get it to do what you want across all UI Styles

Or as someone else pointed out, disable the VisualStyles for your application.

Original

As far as I know, the rendering of the Progress bar happens inline with the windows theme style that you've chosen (win2K, xp, vista)

You can change the color by setting the property

ProgressBar.ForeColor

I'm not sure that you can do much more however...

does some googling

Theres an article here from MS KB on creating a "Smooth" progress bar

http://support.microsoft.com/kb/323116

Solution 10 - C#

try using messsage PBM_SETBARCOLOR, that should do the trick with SendMessage

See http://www.vbforums.com/showthread.php?t=248721 for an example.

Solution 11 - C#

Just in case anyone looks for another option.... you can extend a Panel, use it as background (white or whatever), add another Panel inside it for the foreground (the moving bar). Then you have total control of changing the color, etc.

Solution 12 - C#

All these methods fail to work for me but this method allows you to change it to a color string.

Please note that i found this code from somewhere else on StackOverflow and changed it a little. I have since forgot where i found this code and i can't link it because of that so sorry for that.

But anyway i hope this code helps someone it really did help me.

private void ProgressBar_MouseDown(object sender, MouseButtonEventArgs e)
    {
        var converter = new System.Windows.Media.BrushConverter();
        var brush = (Brush)converter.ConvertFromString("#FFB6D301");
        ProgressBar.Foreground = brush;
    }

Where the name "ProgressBar" is used replace with your own progress bar name. You can also trigger this event with other arguments just make sure its inside brackets somewhere.

Solution 13 - C#

Change Color and Value ( instant change )

Put using System.Runtime.InteropServices; at top...

Call with ColorBar.SetState(progressBar1, ColorBar.Color.Yellow, myValue);

I noticed that if you change the value of the bar ( how big it is ) then it will not change if it is in a color other than the default green. I took user1032613's code and added a Value option.

public static class ColorBar
{
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
    static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr w, IntPtr l);
    public enum Color { None, Green, Red, Yellow }

    public static void SetState(this ProgressBar pBar, Color newColor, int newValue)
    {
        if (pBar.Value == pBar.Minimum)  // If it has not been painted yet, paint the whole thing using defualt color...
        {                                // Max move is instant and this keeps the initial move from going out slowly 
            pBar.Value = pBar.Maximum;   // in wrong color on first painting
            SendMessage(pBar.Handle, 1040, (IntPtr)(int)Color.Green, IntPtr.Zero);
        }
        pBar.Value = newValue;
        SendMessage(pBar.Handle, 1040, (IntPtr)(int)Color.Green, IntPtr.Zero);     // run it out to the correct spot in default
        SendMessage(pBar.Handle, 1040, (IntPtr)(int)newColor, IntPtr.Zero);        // now turn it the correct color
    }

}

Solution 14 - C#

Simply right click on your project in Visual Basic Solution Explorer (where your vb files are) and select properties from the menu. In the window that pops up deselect "Enable XP Visual Styles" and now when you set forecolor, it should work now.

Solution 15 - C#

Vertical Bar UP For Down in red color :

using System;
using System.Windows.Forms;
using System.Drawing;



public class VerticalProgressBar : ProgressBar
{
    

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.Style |= 0x04;
            return cp;
            
        }
    }
    private SolidBrush brush = null;

    public VerticalProgressBar()
    {
        this.SetStyle(ControlStyles.UserPaint, true);
    }
    
    protected override void OnPaint(PaintEventArgs e)
    {
        if (brush == null || brush.Color != this.ForeColor)
            brush = new SolidBrush(this.ForeColor);

        Rectangle rec = new Rectangle(0, 0, this.Width, this.Height);
        if (ProgressBarRenderer.IsSupported)
        ProgressBarRenderer.DrawVerticalBar(e.Graphics, rec);
        rec.Height = (int)(rec.Height * ((double)Value / Maximum)) - 4;
        rec.Width = rec.Width - 4;
        e.Graphics.FillRectangle(brush, 2, 2, rec.Width, rec.Height);
       
    } 
}

Solution 16 - C#

Јοеу: Quote: Usually the progress bar is either themed or honors the user's color preferences. So for changing the color you either need to turn off visual styles and set ForeColor or draw the control yourself.

As for the continuous style instead of blocks you can set the Style property:

pBar.Style = ProgressBarStyle.Continuous;

ProgressBarStyle.Continuous versus Blocks is useless with VistualStyles enabled...

Block(s) will only work with visual styles disabled ... which renders all of this a moot point (with regards to custom progress color) With vistual styles disabled ... the progress bar should be colored based on the forecolor.

I used a combination of William Daniel's answer (with visual styles enabled, so the ForeColor will not just be flat with no style) and Barry's answer (to custom text on the progress bar) from: https://stackoverflow.com/questions/3529928/how-do-i-put-text-on-progressbar

Solution 17 - C#

The VB.Net colored progressbar which respects WXP Visual Styles answer is ...

I started with the answer from 'user1032613' on 3/17/12. Note that this is now a Module, not a class. From there I converted the code but more was needed. In particular the converted code showed a DirectCast function to convert the 'state' integer to a IntPtr type which didn't work.

Imports System.Runtime.InteropServices

Public Module ModifyProgressBarColor

    Private Declare Function SendMessage Lib "User32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) As Long

    <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=False)> _
    Private Function SendMessage(hWnd As IntPtr, Msg As UInteger, w As IntPtr, l As IntPtr) As IntPtr
    End Function

    <System.Runtime.CompilerServices.Extension()> _
    Public Sub SetState(pBar As ProgressBar, state As Integer)

	    '-- Convert state as integer to type IntPtr
	    Dim s As IntPtr
	    Dim y As Integer = state
	    s = IntPtr.op_Explicit(y)

	    '-- Modify bar color
	    SendMessage(pBar.Handle, 1040, s, IntPtr.Zero)

    End Sub

End Module

And again just call this in the using code with this line:

Call ModifyProgressBarColor.SetState(prb, 2)

BTW - I tried other colors - 0, 4, 5 - they all just displayed green.

Solution 18 - C#

I know its way too old to be answered now.. but still, a small tweak to @[Daniel][1]'s answer for rectifying the problem of not showing zero valued progress bar. Just draw the Progress only if the inner rectangle's width is found to be non-zero.

[1]: https://stackoverflow.com/users/193811/william-daniel "Daniel" Thanks to all the contributers.

        public class ProgressBarEx : ProgressBar
        {
            public ProgressBarEx()
            {
                this.SetStyle(ControlStyles.UserPaint, true);
            }

            protected override void OnPaintBackground(PaintEventArgs pevent){}
                // None... Helps control the flicker.                

            protected override void OnPaint(PaintEventArgs e)
            {
                const int inset = 2; // A single inset value to control teh sizing of the inner rect.

                using (Image offscreenImage = new Bitmap(this.Width, this.Height))
                {
                    using (Graphics offscreen = Graphics.FromImage(offscreenImage))
                    {
                        Rectangle rect = new Rectangle(0, 0, this.Width, this.Height);

                        if (ProgressBarRenderer.IsSupported)
                            ProgressBarRenderer.DrawHorizontalBar(offscreen, rect);

                        rect.Inflate(new Size(-inset, -inset)); // Deflate inner rect.
                        rect.Width = (int)(rect.Width * ((double)this.Value / this.Maximum));

                        if (rect.Width != 0)
                        {
                            LinearGradientBrush brush = new LinearGradientBrush(rect, this.ForeColor, this.BackColor, LinearGradientMode.Vertical);
                            offscreen.FillRectangle(brush, inset, inset, rect.Width, rect.Height);
                            e.Graphics.DrawImage(offscreenImage, 0, 0);
                            offscreenImage.Dispose();
                        }
                    }
                }
            }
        }

Solution 19 - C#

I found this can be done by drawing a rectangle inside the progress bar, and to set its width according to the progress's current value. I also added support for right to left progress. This way you don't need to use the Image, and since Rectnalge.Inflate isn't called the drawn rectangle is smaller.

public partial class CFProgressBar : ProgressBar
{
    public CFProgressBar()
    {
        InitializeComponent();
        this.SetStyle(ControlStyles.UserPaint, true);
    }

    protected override void OnPaintBackground(PaintEventArgs pevent) { }

    protected override void OnPaint(PaintEventArgs e)
    {
        double scaleFactor = (((double)Value - (double)Minimum) / ((double)Maximum - (double)Minimum));
        int currentWidth = (int)((double)Width * scaleFactor);
        Rectangle rect;
        if (this.RightToLeftLayout)
        {
            int currentX = Width - currentWidth;
            rect = new Rectangle(currentX, 0, this.Width, this.Height);
        }
        else
            rect = new Rectangle(0, 0, currentWidth, this.Height);

        if (rect.Width != 0)
        {
            SolidBrush sBrush = new SolidBrush(ForeColor);
            e.Graphics.FillRectangle(sBrush, rect);
        }
    }
}

Solution 20 - C#

I think that the simplest solutions of all, it's just a quick fix, but you can delete, comment the Application.EnableVisualStyles() from Program.cs, or however you have name your the part containing the Main function. After that you can freely change the color form the progress bar by progressBar.ForeColor = Color.TheColorYouDesire;

static void Main()
        {
            //Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
         }

Solution 21 - C#

Edit: in the two minuites it took me to fire up vs and check the syntax i was beaten to it with much better responses. i love this site.

        progressBar1 = new ProgressBar();
        progressBar1.ForeColor = Color.Red;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionIvan ProdanovView Question on Stackoverflow
Solution 1 - C#user1032613View Answer on Stackoverflow
Solution 2 - C#CrispyView Answer on Stackoverflow
Solution 3 - C#William DanielView Answer on Stackoverflow
Solution 4 - C#dustyburwellView Answer on Stackoverflow
Solution 5 - C#Josh M.View Answer on Stackoverflow
Solution 6 - C#Matt BlaineView Answer on Stackoverflow
Solution 7 - C#MarcView Answer on Stackoverflow
Solution 8 - C#JoeyView Answer on Stackoverflow
Solution 9 - C#Eoin CampbellView Answer on Stackoverflow
Solution 10 - C#AleksandarView Answer on Stackoverflow
Solution 11 - C#EduardoView Answer on Stackoverflow
Solution 12 - C#EpicNinjaCheeseView Answer on Stackoverflow
Solution 13 - C#SparfyView Answer on Stackoverflow
Solution 14 - C#RandyView Answer on Stackoverflow
Solution 15 - C#MandrovaView Answer on Stackoverflow
Solution 16 - C#NeoH4x0rView Answer on Stackoverflow
Solution 17 - C#DanW52View Answer on Stackoverflow
Solution 18 - C#Divins MathewView Answer on Stackoverflow
Solution 19 - C#ZOKView Answer on Stackoverflow
Solution 20 - C#Mladen TasevskiView Answer on Stackoverflow
Solution 21 - C#FusspawnView Answer on Stackoverflow