winforms 防止自定义ProgressBar Flink

hpxqektj  于 7个月前  发布在  Flink
关注(0)|答案(1)|浏览(77)

对于我正在制作的应用程序,我根据William丹尼尔制作的程序定制了一个ProgressBar:How to change the color of progressbar in C# .NET 3.5?
在用较低的百分比值做了一些测试后,我注意到这个奇怪的 Flink :

我试着将DoubleBuffered设置为true,但它们仍然显示。
有人知道为什么会出现这些奇怪的线条吗?

osh3o9ms

osh3o9ms1#

那不是“ Flink ”,那是一种“撕裂”。自定义控件并不总是完全绘制;如果你有一个闭合循环,不允许窗体正确地重绘自身和其子控件,就可能发生这种情况。
也可以使填充ProgressBar的过程异步。
一些建议的修改,以 * 使其更平滑 *:

如果为true,则控件首先绘制到缓冲区,而不是直接绘制到屏幕,这样可以减少 Flink 。如果将此属性设置为true,则还应将AllPaintingInWmPaint设置为true。

  • 然后设置**ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint**:

AllPaintingInWmPaint:如果为true,控件将忽略窗口消息WM_ERASEBKGND以减少 Flink 。仅当UserPaint位设置为true时才应用此样式。
UserPaint:如果为true,则控件绘制自己,而不是操作系统。如果为false,则不引发Paint事件。此样式仅适用于从Control派生的类。

  • ControlStyles.Opaque删除背景,让ProgressBarRenderer完成其工作,以填充ProgressBar的基础图形。

根据当前Value集合计算ProgressBar的彩色部分的当前宽度:
float width = (this.Width - 3) * ((float)this.Value / this.Maximum)
如果**width > 0**,则使用Forecolor和BackColor属性绘制ProgressBar颜色。当然,您可以使用一组不同的属性来定义这些颜色。
添加一些抗锯齿到绘图中,设置Graphics.SmoothingMode,使LinearGradientBrush生成的颜色过渡更平滑。这在设置LinearGradientMode.Horizontal时更有用。
导致:

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

作为一个小的改进,您可以在ProgressBar的顶部绘制一条高度为9像素的半透明颜色的线,以模拟原始的 * 反射 *。
更改代码以添加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);
}

相关问题