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

22

109

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.

Fiche answered 22/4, 2009 at 19:2 Comment(0)
F
93

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

Fowler answered 22/4, 2009 at 19:42 Comment(7)
That's really cool, thanks. It really helped me out on something I'm working on at the moment, though I changed it to repaint the whole control each time instead of just the area specified by e.ClipRectangle. Otherwise, it didn't repaint correctly after only part of the control was invalidated by another window or the edge of the screen.Petiolule
@Matt Blaine: Could you please post your modification as an edit to the answer? I believe there will be enough people interested in your complete solution.Diacid
@Diacid Just noticed your comment. I don't have enough rep to edit the answer, so I posted my own. Thanks. #779178Petiolule
I realize this is old; and I realize this is a nit (because Minimum is almost always zero); but the Width scale factor should be (((double)Value - (double)Minimum) / ((double)Maximum - (double)Minimum)) to be anal-retentively correct. :)Domenech
A bump after a long time. Sorry for bumping but I wanted to additionally ask something regarding the background of the progress bar. Is there a more optimized / better way to change the background to a specific color (so that it doesn't use the visual style for the background) than the one below? e.Graphics.FillRectangle(DarkGray, rec.Width, 0, e.ClipRectangle.Width, e.ClipRectangle.Height);Fifteen
@ChrisPersichetti: Can this be modified to work with 'Marquee' style?Ammadas
Why mine is still color green? I copied your code, please help.Metalanguage
G
139

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).

Gratiana answered 17/3, 2012 at 20:8 Comment(12)
You created an extension method, so the call should be progressBar1.SetState(2); besides from that, Great answer!Predator
Should be noted that this is only available on Vista+. You can view the full documentation by searching for PBM_SETSTATE.Linkoski
+1. Thanks! Tip for others that got me: Paste this at the end of the namespace instead of at the beginning if you get this error during runtime: System.Resources.MissingManifestResourceExceptionHangbird
This is amazing, but it breaks my progress bar partially, it will never fill up 100% ....Softball
I am getting some strange behavior for my progress bar. It doesn't update the color all the time and sometimes it only updates after a control resizes or moves.Raine
@Raine same here :(Hemorrhage
Can this be modified for other colors? I need blue... Has anyone figured out Norbert's question about not filling 100%?Carminecarmita
in my case ive got an error. i just removes the "this" and everything was fine: public static void SetState(/*this*/ProgressBar pBar, int state)Sclerotic
public const uint PBM_SETSTATE = 0x0410; // 1040Fasto
@user1032613: Can this be class be modified to get colors beyond red, yellow and green? If yes, how to achieve this?(Actually i need a custom RGB color to be set).Ammadas
Thanks! Though I have visited this question earlier when I was roaming here but I didn't know I'll be using this solution after such a long time..Transformer
@Raine same here; also, marquee effect doesn't workInexcusable
F
93

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

Fowler answered 22/4, 2009 at 19:42 Comment(7)
That's really cool, thanks. It really helped me out on something I'm working on at the moment, though I changed it to repaint the whole control each time instead of just the area specified by e.ClipRectangle. Otherwise, it didn't repaint correctly after only part of the control was invalidated by another window or the edge of the screen.Petiolule
@Matt Blaine: Could you please post your modification as an edit to the answer? I believe there will be enough people interested in your complete solution.Diacid
@Diacid Just noticed your comment. I don't have enough rep to edit the answer, so I posted my own. Thanks. #779178Petiolule
I realize this is old; and I realize this is a nit (because Minimum is almost always zero); but the Width scale factor should be (((double)Value - (double)Minimum) / ((double)Maximum - (double)Minimum)) to be anal-retentively correct. :)Domenech
A bump after a long time. Sorry for bumping but I wanted to additionally ask something regarding the background of the progress bar. Is there a more optimized / better way to change the background to a specific color (so that it doesn't use the visual style for the background) than the one below? e.Graphics.FillRectangle(DarkGray, rec.Width, 0, e.ClipRectangle.Width, e.ClipRectangle.Height);Fifteen
@ChrisPersichetti: Can this be modified to work with 'Marquee' style?Ammadas
Why mine is still color green? I copied your code, please help.Metalanguage
S
41

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);
            }
        }
    }
}
Spool answered 20/9, 2011 at 19:44 Comment(9)
Well this is the closest to original implemantation from Microsoft.Fibril
Having a using block and calling Dispose is actually a bit redundant. Great answer though.Ball
I realize this is old; and I realize this is a nit (because Minimum is almost always zero); but the Width scale factor should be (((double)Value - (double)Minimum) / ((double)Maximum - (double)Minimum)) to be anal-retentively correct. :)Domenech
When I use TextRenderer.DrawText() to draw text into offscreenimage, the final result on screen looks pixellated, and not like a label using the exact same font. Drawing all this directly to e.Graphics without the offscreenimager gives the correct result though... Any ideas why?Undermine
@bitwise Are you asserting that the offscreenimage is the same size as the Graphics you will be writing this new image to? If not, I can imagine how scaling could wind up being a problem. I haven't been working with .Net graphics for a while now, but this seems like the first thing to check out.Spool
Yeah, I did try blitting unscaled. Finally, I just switched to WPF, so everything I need is just built in.Undermine
Great answer. This example should use the following : System.Drawing, System.Drawing.Drawing2D, System.Windows.Forms. LinearGradientBrush also exists in System.Windows.Media, so I was a bit confused at first.Lunate
I would also add that the ForeColor is visible even if the value is 0. I surrounded the brush initialization and FillRectangle method with if (Value > 0) and it worked fine.Lunate
for some reason this gets removed from the toolbox when i try to drop it on the form. I'm using AnyCPU. Any idea what might be causing this ?Nationalism
M
31

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

Macmullin answered 22/4, 2009 at 19:7 Comment(5)
Forecolor=red ; Backcolor=blue; Style = Continious. Nothing changed,its staying like i never touched itFiche
bah...okay, I see the problem. You need to disable visual styles in order for this to work with the properties. It's probably painting using whatever theme you have selected. In Program.cs there's a line that reads Application.EnableVisualStyles(). Remove that line and this will work. Otherwise, you'll need to paint the control yourself. The other option is to use WPF (if it's a possibility), since it lets you do this kind of stuff really easily.Macmullin
Please give me more information about "How to paint it by myself".Fiche
Here's a tutorial on owner drawing a progress bar. The process is much too complicated for a comment. codeproject.com/KB/cpp/VistaProgressBar.aspxMacmullin
It is a shame Application.EnableVisualStyles() is the key part of this solution. Unfortunately this breaks all other styles.Octa
P
20

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#

Provisional answered 11/4, 2011 at 14:18 Comment(1)
I know it's old, but -- this code will error out once it hits a value of 4, due to LinearGradientBrush reading the rec width as 0. Easiest fix is to not do the "padding" of 4px in the code and instead place it in a panel or something with padding (if you want a border) and making rec.Width = (int)((rec.Width * scaleFactor) - 4) into rec.Width = (int)(rec.Width * scaleFactor) + 1Pennate
P
16

Modification 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);
    }
}
Petiolule answered 23/3, 2010 at 6:41 Comment(3)
This works great for changing the foreground color, but it flickers a lot, whereas the default ProgressBar control does not. Any idea how to solve this?Casabonne
I've found out how to solve the flickering: add double-buffering to the ControlStyles of the user-defined ProgressBar, like this: SetStyle(ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, ...).Casabonne
I realize this is old; and I realize this is a nit (because Minimum is almost always zero); but the Width scale factor should be (((double)Value - (double)Minimum) / ((double)Maximum - (double)Minimum)) to be anal-retentively correct. :)Domenech
C
6

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);
  }
Canary answered 31/5, 2010 at 14:22 Comment(1)
+1: I think this is what most people meant by red. Making it show an error state.Hardaway
P
3

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;
Pericarditis answered 22/4, 2009 at 19:11 Comment(0)
U
2

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

Umont answered 22/4, 2009 at 19:9 Comment(1)
@Eion,Forecolor=red ; Backcolor=blue; Style = Continious. Nothing changed,its staying like i never touched it.Fiche
D
2

try using message PBM_SETBARCOLOR, that should do the trick with SendMessage.

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

Dartmouth answered 18/12, 2009 at 8:36 Comment(0)
B
2

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.

Beckham answered 28/1, 2011 at 15:5 Comment(1)
This was the easiest. I had flicker and other issues with some of the other solutions. I just put a panel in the same spot as the PB with the same anchors but overtop of the PB and then changed the panel.width to the calculated percent of the PB width.Jaunita
S
2

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.

Strobile answered 27/10, 2014 at 2:44 Comment(1)
nice work..I'm using inside a ProgressChanged event to go from light to dark...+1Machinist
U
2

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
    }

}
Uproarious answered 21/5, 2015 at 16:51 Comment(1)
We had to flip pBar.Value = pBar.Maximum; and SendMessage(pBar.Handle, 1040, (IntPtr)(int)Color.Green, IntPtr.Zero); inside of the condition-body for the progress to show the correct new color.Cameo
W
1

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.

Willowwillowy answered 26/9, 2011 at 0:12 Comment(0)
N
1

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);

    } 
}
Nadia answered 10/10, 2013 at 20:44 Comment(2)
Can you please explain either in text or in comments to the code how this solves the problem.Rives
I realize this is a nit (because Minimum is almost always zero); but the Height scale factor should be (((double)Value - (double)Minimum) / ((double)Maximum - (double)Minimum)) to be anal-retentively correct. :)Domenech
S
0

Јοеу:

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 VisualStyles 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 visual 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: How do I put text on ProgressBar?

Su answered 5/6, 2013 at 3:3 Comment(0)
T
0

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.

Thionic answered 28/10, 2013 at 16:26 Comment(0)
C
0

I know its way too old to be answered now.. but still, a small tweak to @Daniel'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.

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();
                        }
                    }
                }
            }
        }
Chromatin answered 3/12, 2016 at 8:9 Comment(0)
H
0

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);
        }
    }
}
Hafnium answered 15/7, 2018 at 10:54 Comment(0)
P
0

I know that this post is super old and the question may no longer be relevant, but I decided to make my own version of a colored ProgressBar. Also, you can add a border to the progress bar and change its color. These values are called BorderColor and ShowBorder.

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

public class ProgressBarEx : ProgressBar
{
    private bool showBorder = false;
    private Color borderColor = Color.Black;

    public bool ShowBorder { get => showBorder; set { showBorder = value; Invalidate(); } }
    public Color BorderColor { get => borderColor; set { borderColor = value; Invalidate(); } }

    public ProgressBarEx()
    {
        SetStyle(ControlStyles.UserPaint, true);
        ForeColor = Color.Gray;
        BackColor = Color.White;
    }

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

        using (var backgroundBrush = new SolidBrush(BackColor))
            e.Graphics.FillRectangle(backgroundBrush, rec);

        var progressBarWidth = (int)(rec.Width * ((double)Value / Maximum));
        var progressBarHeight = rec.Height;

        using (var barBrush = new SolidBrush(ForeColor))
            e.Graphics.FillRectangle(barBrush, 0, 0, progressBarWidth, progressBarHeight);

        if (showBorder)
        {
            using (var pen = new Pen(borderColor))
                e.Graphics.DrawRectangle(pen, rec.X, rec.Y, rec.Width - 1, rec.Height - 1);
        }
    }
}
Palpate answered 2/4, 2023 at 12:19 Comment(0)
R
-1

I think that the simplest solution of all, is just a quick fix but you can delete or comment out the Application.EnableVisualStyles() from `Program.cs, or however you have name 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());
         }
Rumormonger answered 10/4, 2019 at 14:26 Comment(1)
This makes the UI very uglyAhvenanmaa
S
-5

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;
Socle answered 22/4, 2009 at 19:10 Comment(5)
Doesn't work.It stays empty now,i added progressBar1.value = 50,but still emptyFiche
tried setting the maxiumum value ? progressBar1 = new ProgressBar(); progressBar1.ForeColor = Color.Red; progressBar1.Maximum = 100;Socle
No,the problem is in my windows theme.Fiche
No idea if this will work, but try commenting out Application.EnableVisualThemes(); that is in one of the prebuilt files vs generate's ( I cant recall what one )Socle
Application.EnableVisualStyles() sorry not themesSocle

© 2022 - 2024 — McMap. All rights reserved.