Reputation: 6128
Is there a possbility to disable animation of the progress bar?
I need it for some pocess which is paused and not running at the moment. An average user would think the process is running if the progress bar is being blinking.
The advice to create own progress bar control is not what I'm looking for.
Upvotes: 13
Views: 22036
Reputation: 11
I am also a little annoyed with the animation in the progress fillers, and the property for setting the animation speed to 0 (zero) didn't have any effect on a WinForms in dot net 8. So I found this post.
The first solution is elegant, but didn't work for me. I assume the post, being from 2010, is way too old and WM_ThisOrThat may have changed values in the meantime... Cannot rely on constant values! I could probably look them up in the Windows SDK, but who knows when they will change again.
So I took a look at the other suggestions (1, 2). And yes, both work, with some tweaks. Here's my code, inspired from the other answers, and it works like a charm.
Tweak the brushes and pens as you wish to make your own flavor.
public class MyProgressBar : ProgressBar
{
private SolidBrush _brush = new(SystemColors.ControlDark);
private SolidBrush _bkgr = new(SystemColors.Control);
private Pen _border = new(SystemColors.ControlDarkDark, 2);
public MyProgressBar()
{
// Setting these styles does the trick of sending paint message to OnPaint().
// I did not spend any time understanding the details of why :-)
SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.ResizeRedraw,
true);
}
protected override void OnPaint(PaintEventArgs e)
{
// base.OnPaint(e); // Don't call base class.
// Make sure to use a float. In my case I needed to show a
// percentage, which didn't work using the second downvoted answer.
float fillRatio = (float)Value / (float)Maximum;
int fillTo = (int)((float)Width * fillRatio);
e.Graphics.FillRectangle(_brush, 0, 0, fillTo, Height);
e.Graphics.FillRectangle(_bkgr, fillTo, 0, Width, Height);
e.Graphics.DrawRectangle(_border, 0, 0, Width, Height);
}
public new int Value
{
get {return base.Value;}
set {base.Value = value; Invalidate();} // Remember to invalidate.
}
}
Upvotes: 1
Reputation: 4519
My workaround was to use a Panel Control instead of ProgressBar. I changed BackColor, BorderStyle (to Fixed3D) and I manipulate its Width to display needed level of progress. I assumed that 100% of progress is equal to Width of the Form.
Upvotes: 4
Reputation: 1
Paste this as to code. This will rewrite the progress bar, it's also customizable to color.
public class CProgressBar : ProgressBar
{
public Color MyColor {
get { return _color; }
set {
_color = value;
MyBrush = new SolidBrush(_color);
Invalidate();
}
}
private Color _color = Color.Green;
public CProgressBar()
{
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, true);
}
public int Value {
get { return _value; }
set {
_value = value;
Invalidate();
}
}
private int _value;
private SolidBrush MyBrush = new SolidBrush(_color);
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.FillRectangle(MyBrush, new Rectangle(0, 0, Width * (_value / Maximum), Height));
}
}
Upvotes: -2
Reputation: 887469
You can use the Vista progress bar's paused state, like this:
// Assuming a Form1 with 3 ProgressBar controls
private void Form1_Load(object sender, EventArgs e)
{
SendMessage(progressBar2.Handle,
0x400 + 16, //WM_USER + PBM_SETSTATE
0x0003, //PBST_PAUSED
0);
SendMessage(progressBar3.Handle,
0x400 + 16, //WM_USER + PBM_SETSTATE
0x0002, //PBST_ERROR
0);
}
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern uint SendMessage(IntPtr hWnd,
uint Msg,
uint wParam,
uint lParam);
Upvotes: 23
Reputation: 2757
You could override the OnPaint() of the progressbar. You don't actually need to rewrite the whole thing, you just have to inherit the progressbar and override OnPaint like this:
public class my_progress_bar : ProgressBar {
public Brush brush;
public my_progress_bar() {
this.SetStyle(ControlStyles.UserPaint, true);
brush = Brushes.ForestGreen;
}
protected override void OnPaint(PaintEventArgs e)
{
//base.OnPaint(e);
Rectangle rectangle = e.ClipRectangle;
rectangle.Width = (int)(rectangle.Width * ((double)Value / Maximum)) - 4;
ProgressBarRenderer.DrawHorizontalBar(e.Graphics, e.ClipRectangle);
rectangle.Height = Height - 4;
e.Graphics.FillRectangle(brush, 2, 2, rectangle.Width, rectangle.Height);
}
}
Upvotes: -1
Reputation: 63126
What you will want to do is set the style on this control specifically to override the theme changes. This article gives you a bit of information.
Upvotes: 0
Reputation: 185643
The standard means of communicating to a user that an action is either paused or can't be accurately measured is to use the marquee display style.
progressBar1.Style = ProgressBarStyle.Marquee;
This style ignores the Maximum
and Value
properties and displays a progress bar "segment" that continually moves across the progress bar and loops around (it doesn't fill the progress bar, it moves what looks like a section of the bar all the way across the control and around to the beginning again.)
Upvotes: 3