禁用 WinForms 进度条动画

13

有没有可能禁用进度条的动画效果?

我需要禁用它,因为某些过程已经暂停,此时如果进度条一直闪烁,普通用户会认为该过程正在运行。

建议创建自己的进度条控件并不是我想要的。


1
你是在谈论Vista的图形效果吗?一个跑马灯条? - SLaks
是的。XP、Vista和W7都会受到影响。 - Vasyl Boroviak
这可能与https://social.msdn.microsoft.com/Forums/vstudio/en-US/d223204c-24ab-4ca5-bb45-1400e3af2922/is-there-a-progress-bar-alternative-available-from-nuget-for-windows-7-that-sets-it-value-without?forum=csharpgeneral和http://stackoverflow.com/questions/37625930/cannot-get-progressbar-animation-with-code-progresschanged-not-called有关。 - barlop
1
@JimFell 感谢您投票关闭此问题。然而,如果您仔细阅读,您会发现这些问题完全不同。请查看它们的已接受答案。 - Vasyl Boroviak
6个回答

23
你可以使用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);

1
那正是我在寻找的!谢谢你。那个项目很棒:http://windowsformsaero.codeplex.com/ - Vasyl Boroviak
刚刚遇到了同样的问题。不过,有一个问题:这个解决方案也适用于将要在XP上运行的软件吗?还是仅适用于Vista / Win7? - Julian
链接指向一个缺失的页面。最好将相关信息复制粘贴到答案中。 - dbkk
@SLaks 有没有办法在绿色时去掉发光效果? - Isuru

4
我的解决方法是使用一个Panel控件代替ProgressBar。我改变了它的BackColor、BorderStyle(改为Fixed3D),并且通过操纵其Width来显示所需的进度水平。我假设100%的进度等于窗体的宽度。

Panel as a ProgressBar


3

向用户传达某个动作已暂停或无法准确测量的标准方式是使用跑马灯显示样式。

progressBar1.Style = ProgressBarStyle.Marquee;

这种样式忽略了MaximumValue属性,显示了一个进度条“段”,该段不断地在进度条上移动并循环(它不会填充进度条,而是将看起来像一部分进度条的东西移动到控件的整个范围内,然后再回到开头。)


谢谢。但我需要最大值和数值。用户需要看到进程暂停的位置。 - Vasyl Boroviak
@Vasily:这是唯一与操作系统无关的过程;如果你保证使用的是Vista或7,则SLak的答案应该可以解决你的问题。 - Adam Robinson

0
你需要做的是将此控件的样式设置为覆盖主题更改。这篇文章会给你一些信息。

http://www.codeproject.com/KB/cpp/ExtendedProgressbar.aspx 看起来不错。但我怀疑我的老板是否会批准非标准外观的控件。 - Vasyl Boroviak

-1
你可以重写进度条的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);
        }
    }

你误解了 e.ClipRectangle;这样渲染不正确。此外,你需要一个Vista风格的进度条。调用 ProgressBarRenderer.DrawHorizontalChunks 会让它看起来更好一些。 - SLaks
e.ClipRectangle 是需要重新绘制的区域。您应该使用 this.ClientRectangle - SLaks
正如我在我的问题中所说:“创建自己的进度条控件的建议并不是我所寻找的。” - Vasyl Boroviak
这个答案完全是错误的。在进度条中,OnPaint()从来不会被调用,因为进度条是由Windows(UxTheme.dll)绘制而不是由.NET框架绘制的。 - Elmue

-2

将此粘贴为代码。这将重写进度条,也可以自定义颜色。

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

顺便说一句,它正在工作。如果有人计算这个倒计时,那就意味着他太吝啬了,不愿意自己尝试。 - ad48
我理解你的感受,只是点踩而不说明原因确实很无礼。虽然在使用 .Net 4.5 时代码存在许多问题:类需要是部分类,MyBrush 不能用非静态值初始化,最终什么也没有被绘制。我错在哪里了? - Xan-Kun Clark-Davis
1
由于整数转换,Width * (_value / Maximum) 始终为零。 - Xan-Kun Clark-Davis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接