是否可以禁用进度条的动画?
我需要它来执行某些已暂停且目前未运行的进程。如果进度条闪烁,普通用户会认为进程正在运行。
创建自己的进度条控件的建议不是我想要的。
您可以使用 Vista 进度条的暂停状态,像这样:
// 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);
向用户传达操作已暂停或无法准确测量的标准方法是使用选取框显示样式。
progressBar1.Style = ProgressBarStyle.Marquee;
此样式忽略
Maximum
和 Value
属性,并显示一个进度条“段”,该段不断地在进度条上移动并循环(它不会填充进度条,它移动的内容看起来像是进度条的一部分)一直穿过控件并再次回到开头。)
您需要做的是专门设置此控件的样式以覆盖主题更改。这篇文章为您提供了一些信息。
我对进度填充中的动画也有点恼火,将动画速度设置为 0(零)的属性对 dot net 8 中的 WinForms 没有任何影响。所以我找到了这篇文章。
第一个解决方案很优雅,但对我来说不起作用。我认为该帖子是 2010 年发布的,太旧了,并且 WM_ThisOrThat 可能同时更改了值不能依赖常量值!我可能可以在 Windows SDK 中查找它们,但谁知道它们什么时候会再次更改。
所以我看了一下那些被否决的建议。是的,两者都可以工作,但需要进行一些调整。对他们投反对票是不正确的。这是我的代码,灵感来自被否决的答案,它的作用就像一个魅力。
根据自己的喜好调整画笔和笔。
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.
}
}
您可以重写进度条的OnPaint()。你实际上不需要重写整个事情,你只需要继承进度条并重写 OnPaint ,如下所示:
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);
}
}
将此粘贴到代码中。这将重写进度条,它也可以自定义颜色。
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));
}
}