尽管双缓冲,该股票仍然闪烁 [英] Despite double buffering, the ticker still flickers

查看:197
本文介绍了尽管双缓冲,该股票仍然闪烁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有人有关于如何摆脱闪烁的想法?我研究了SO,网络,以及试行就像把TickerControl成一个双缓冲面板一拉的时的OnPaint不拉丝()双缓冲:为什么没有工作等,除了许多其他的事情?它仍然闪烁,而不是在每一个重画,但每秒几次



另外,即使在OnPaint中除去g.Clear(背景色)之后,东西必须。还是清算的背景下,作为文本继续可读性滚动



下面我TickerControl类的相关部分:

 类TickerControl:控制
{
私人静态只读的StringFormat的StringFormat =新的StringFormat(StringFormatFlags.NoWrap);

私人const int的填充= 40;
私人const int的scrollSleep = 10;
私人const int的scrollAdvancePixels = 1;

私人浮动输出textWidth;
私人浮动currentX;

私人静态只读定时器scrollTimer =新的Timer();

公共TickerControl()
{
this.SetStyle(ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer
,真);
scrollTimer.Tick + = AdvanceText;
scrollTimer.Interval = scrollSleep;
scrollTimer.Enabled = TRUE;
}

私人无效AdvanceText(对象发件人,EventArgs五)
{
如果(IsDisposed)
的回报;

currentX - = scrollAdvancePixels;
如果(currentX< = -textWidth)
currentX = 0;
的Invalidate();
}

保护覆盖无效OnPaintBackground(PaintEventArgs的pevent)
{
}

保护覆盖无效的OnPaint(PaintEventArgs的E)
{
图形G = e.Graphics;

g.Clear(背景色);使用

(SolidBrush刷=新SolidBrush(前景色))
{
g.DrawString(文字,字体,画笔,currentX,0,的StringFormat);
g.DrawString(文字,字体,画笔,currentX +输出textWidth,0,的StringFormat);
}
}



任何想法?



更新:



由于sallushan建议手动双缓冲,让我补充一点,我已经试过前使用下面的代码。但是在屏幕上,它看起来酷似上面,所以看起来问题不骗我OnPaint方法中。我猜那一定是在我的控制的设置某处

 私人位图后备缓冲; 

保护覆盖无效的OnPaint(PaintEventArgs的E)
{
如果(后备缓冲== NULL)
后备缓冲=新位图(this.ClientSize.Width,this.ClientSize 。高度);

图形G = Graphics.FromImage(后备缓冲);

g.Clear(背景色);使用

(SolidBrush刷=新SolidBrush(前景色))
{
g.DrawString(文字,字体,画笔,currentX,0,的StringFormat);
g.DrawString(文字,字体,画笔,currentX +输出textWidth,0,的StringFormat);
}

g.Dispose();

e.Graphics.DrawImageUnscaled(后备缓冲,0,0);
}

保护覆盖无效OnPaintBackground(PaintEventArgs的pevent)
{
//别叫基地!
}

保护覆盖无效OnSizeChanged(EventArgs的发送)
{
如果(后备缓冲!= NULL)
{
backBuffer.Dispose( );
后备缓冲= NULL;
}
base.OnSizeChanged(E);
}


解决方案

打开汉斯帕桑特的评论成答案,这样我可以接受它:




这效果不叫忽悠,它被称为撕裂。你看老的位图的一部分
和新位图的一部分。它变得非常
明显的在运动的物体,它们出现抖动。没有可以解决在
的WinForms,谷歌垂直消隐间隔。 - 汉斯帕桑特



Does anyone have an idea about how to get rid of flickering? I researched on SO, the web, and tried out many different things like putting TickerControl into a double buffered Panel a la Double Buffering when not drawing in OnPaint(): why doesn't it work? etc. besides many other things. It still flickers, not on every repaint, but a couple times per second.

Also, even after removing the "g.Clear(BackColor)" in OnPaint, something must still be clearing the background, as the text continues to scroll readably.

Here the relevant parts of my TickerControl class:

class TickerControl : Control
{
    private static readonly StringFormat stringFormat = new StringFormat(StringFormatFlags.NoWrap);

    private const int padding = 40;
    private const int scrollSleep = 10;
    private const int scrollAdvancePixels = 1;

    private float textWidth;
    private float currentX;

    private static readonly Timer scrollTimer = new Timer();

    public TickerControl()
    {
        this.SetStyle(ControlStyles.UserPaint |
                      ControlStyles.AllPaintingInWmPaint |
                      ControlStyles.OptimizedDoubleBuffer
                      , true);
        scrollTimer.Tick += AdvanceText;
        scrollTimer.Interval = scrollSleep;
        scrollTimer.Enabled = true;
    }

    private void AdvanceText(object sender, EventArgs e)
    {
        if (IsDisposed)
            return;

        currentX -= scrollAdvancePixels;
        if (currentX <= -textWidth)
            currentX = 0;
        Invalidate();
    }

    protected override void OnPaintBackground(PaintEventArgs pevent)
    {
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        Graphics g = e.Graphics;

        g.Clear(BackColor);

        using (SolidBrush brush = new SolidBrush(ForeColor))
        {
            g.DrawString(Text, Font, brush, currentX, 0, stringFormat);
            g.DrawString(Text, Font, brush, currentX + textWidth, 0, stringFormat);
        }
    }

Any ideas?

Update:

As sallushan suggested manual double buffering, let me add that I had tried that before, using the code below. But on screen it looks exactly like the above, so the problem does not seem to lie inside my OnPaint method. I guess it must be somewhere in the setup of my Control.

    private Bitmap backBuffer;

    protected override void OnPaint(PaintEventArgs e)
    {
        if (backBuffer == null)
            backBuffer = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);

        Graphics g = Graphics.FromImage(backBuffer);

        g.Clear(BackColor);

        using (SolidBrush brush = new SolidBrush(ForeColor))
        {
            g.DrawString(Text, Font, brush, currentX, 0, stringFormat);
            g.DrawString(Text, Font, brush, currentX + textWidth, 0, stringFormat);
        }

        g.Dispose();

        e.Graphics.DrawImageUnscaled(backBuffer, 0, 0);
    }

    protected override void OnPaintBackground(PaintEventArgs pevent)
    {
        // Don't call base!
    }

    protected override void OnSizeChanged(EventArgs e)
    {
        if (backBuffer != null)
        {
            backBuffer.Dispose();
            backBuffer = null;
        }
        base.OnSizeChanged(e);
    }

解决方案

Turning Hans Passant's comment into an answer so that I can accept it:

This effect is not called flicker, it is called tearing. You see part of the old bitmap and part of the new bitmap. Which becomes very noticeable on moving objects, they appear jittery. Not fixable in Winforms, google "vertical blanking interval". – Hans Passant

这篇关于尽管双缓冲,该股票仍然闪烁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆