How to change the color of progressbar in C# .NET 3.5?
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
Change (custom) ProgressBar color
It has nothing to do with the Property exactly, but the PInvoke is imperfect either in the source or your conversion. I suspect you started with this old C# answer.
Imports System.Runtime.InteropServices
Class NativeMethods
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=False)>
Private Shared Function SendMessage(hWnd As IntPtr,
Msg As UInt32,
w As IntPtr,
l As IntPtr) As IntPtr
End Function
Private Const PBM_SETSTATE = &H400 + 16
Friend Enum PBMStates
Normal = 1
[Error] = 2
Paused = 3
End Enum
Friend Shared Sub SetProgressState(ctl As ProgressBar, state As PBMStates)
SendMessage(ctl.Handle, PBM_SETSTATE, New IntPtr(state), IntPtr.Zero)
End Sub
End Class
According to the MSDN docs, PBM_SETSTATE
returns the previous state. I've ignored that and made it a Sub. Since it only is supposed to be used with a ProgressBar
I it to accept only a ProgressBar
control rather than a control handle (which could be from any control). Finally, the code is Shared
and in a NativeMethods
class so CA will not complain. Usage:
NativeMethods.SetProgressState(ProgressBar1, NativeMethods.PBMStates.Error)
Result:
Visual Studio 2010: Progressbar does not change color?
Locate the following line of code within your solution (tipically in Program.cs):
Application.EnableVisualStyles();
Comment out this line. Now the color of the progress bar will change as expected, but the style of your controls will also change a little. I'm curremtly trying to find a better solution for this myself.
c#.Net Progress Bar Issue
As for first part of your question - try using following constructor for your brush:
new LinearGradientBrush(new Point(0, 0), new Point(0, Height - inset * 2), BackColor, ForeColor);
Your current brush has top control point at Y=inset
- that's why area from Y=0
to Y=inset
is all painted in solid color.
Changing the color of a progressbar in Visual Basic
Import SendMessage
:
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As Integer) As IntPtr
End Function
And use this function:
SendMessage(ProgressBar1.Handle, 1040, 2, 0)
Color codes:
1: green
2: red
3: yellow
Flickering custom ProgressBar
That's not flickering, that's a form of tearing. The Custom Control is not always drawn completely; it can happen if you have a close loop that doesn't allow the Form to repaint itself and its child controls correctly.
Possibly, make the procedure that fills the ProgressBar asynchronous.
Some suggested modifications to make it smoother:
Use floating point values for your calculations (don't cast to
int
), and use a RectagleF to define the bounds of your drawing.Remove the Bitmap and set ControlStyles.OptimizedDoubleBuffer:
If true, the control is first drawn to a buffer rather than directly to the screen, which can reduce flicker. If you set this
property to true, you should also set theAllPaintingInWmPaint
to true.Then of course set
ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint
:AllPaintingInWmPaint
: If true, the control ignores the window messageWM_ERASEBKGND
to reduce flicker.
This style should only be applied if the UserPaint bit is set to true.UserPaint
: If true, the control paints itself rather than the
operating system doing so. If false, the Paint event is not raised.
This style only applies to classes derived from Control.ControlStyles.Opaque
removes the background and lets ProgressBarRenderer do its job, to fill the base graphics of the ProgressBar.
Calculate the current width of ProgressBar's colored parts based on the current Value
set:float width = (this.Width - 3) * ((float)this.Value / this.Maximum)
If width > 0
, then paint the ProgressBar colors using the Forecolor and BackColor properties. Of course you could use a different set of properties to define these colors.
Add some anti-alias to the drawing, setting the Graphics.SmoothingMode, to make the color transition generated by the LinearGradientBrush smoother. This is more useful when you set LinearGradientMode.Horizontal.
Resulting in:
public class ProgressBarCustom : ProgressBar
{
public ProgressBarCustom()
{
this.SetStyle(ControlStyles.OptimizedDoubleBuffer |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.Opaque, true);
}
protected override void OnPaint(PaintEventArgs e)
{
ProgressBarRenderer.DrawHorizontalBar(e.Graphics, ClientRectangle);
float width = (Width - 3) * ((float)Value / Maximum);
if (width > 0) {
var rect = new RectangleF(1, 1, width, Height - 3);
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
using (var brush = new LinearGradientBrush(rect, BackColor, ForeColor, LinearGradientMode.Horizontal)){
e.Graphics.FillRectangle(brush, rect);
}
}
}
}
As a small improvement, you could draw a line 9 pixels in height, with a semi-transparent color, to the top side of the ProgressBar, to simulate the original reflection.
Change the code to add Graphics.DrawLine()
:
// [...]
using (var brush = new LinearGradientBrush(rect, BackColor, ForeColor, LinearGradientMode.Horizontal))
using (var pen = new Pen(Color.FromArgb(40, 240,240,240), 9)) {
e.Graphics.FillRectangle(brush, rect);
e.Graphics.DrawLine(pen, 1.0f, 1.0f, width, 1.0f);
}
How do I change the color of my progress bar in Inno Setup?
You cannot.
The progress bar is styled by the current Windows theme. In the default Windows theme, the progress bar is green (or yellow or red, if the progress bar is in paused or error state, see TNewProgressBar.State
).
You would have to completely reimplement the drawing of the progress bar or disable visual themes of whole installer.
See How to change the color of progressbar in C# .NET 3.5?
With the Inno Setup API it would very difficult if possible at all to reimplement the drawing. And you probably do not want to disable the visual themes.
If you really need the blue color, you may consider implementing the progress bar yourself using TBitmapImage.Bitmap.Canvas
(using methods like .Rectangle
).
A simple example:
var
ProgressImage: TBitmapImage;
procedure InitializeWizard();
begin
ProgressImage := TBitmapImage.Create(WizardForm);
ProgressImage.Parent := WizardForm;
ProgressImage.Left := ScaleX(10);
ProgressImage.Top := WizardForm.ClientHeight - ScaleY(34);
ProgressImage.Width := ScaleX(200);
ProgressImage.Height := ScaleY(20);
ProgressImage.BackColor := clWhite;
ProgressImage.Bitmap.Width := ProgressImage.Width;
ProgressImage.Bitmap.Height := ProgressImage.Height;
end;
procedure DrawProgress(Image: TBitmapImage; Progress: Integer);
var
Canvas: TCanvas;
Width: Integer;
begin
Log(Format('Drawing progress %d', [Progress]));
Canvas := Image.Bitmap.Canvas;
Canvas.Pen.Style := psClear;
Width := Image.Bitmap.Width * Progress / 100
Log(Format('Bar size: %d x %d', [Width, Image.Bitmap.Height]));
Canvas.Brush.Color := clHighlight;
Canvas.Rectangle(1, 1, Width, Image.Bitmap.Height);
Canvas.Brush.Color := clBtnFace;
Canvas.Rectangle(Width - 1, 1, Image.Bitmap.Width, Image.Bitmap.Height);
Canvas.Pen.Style := psSolid;
Canvas.Pen.Mode := pmCopy;
Canvas.Pen.Color := clBlack;
Canvas.Brush.Style := bsClear;
Canvas.Rectangle(1, 1, Image.Bitmap.Width, Image.Bitmap.Height);
end;
procedure CurPageChanged(CurPageID: Integer);
begin
Log(Format('CurPageChanged %d', [CurPageID]));
DrawProgress(ProgressImage, (CurPageID * 100 / wpFinished));
end;
Related Topics
Is There a Reason Image.Fromfile Throws an Outofmemoryexception for an Invalid Image Format
How to Remove Whitespace on Merge
Get the Ip Address of the Remote Host
Large Object Heap Fragmentation
Calling Unix and Linux Shared Object File .So from C#
What Strategies and Tools Are Useful for Finding Memory Leaks in .Net
How to Unserialize PHP Serialized Array/Variable/Class and Return Suitable Object in C#
How Do Prefix (++X) and Postfix (X++) Operations Work
Marshal C++ Struct Array into C#
Kill Some Processes by .Exe File Name
Pass Complex Parameters to [Theory]
How to Get the Active Screen Dimensions
How to Update a Table Using Oledb Parameters
How to Return a Value from a Form in C#