Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Despite double buffering, the ticker still flickers

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);
    }
like image 735
Evgeniy Berezovsky Avatar asked Aug 19 '11 06:08

Evgeniy Berezovsky


People also ask

What is the purpose of double buffering?

The term double buffering is used for copying data between two buffers for direct memory access (DMA) transfers, not for enhancing performance, but to meet specific addressing requirements of a device (esp. 32-bit devices on systems with wider addressing provided via Physical Address Extension).

How do I turn on double buffering?

To enable double buffering, simply call the setDoubleBuffered() method (inherited from JComponent) to set the double-buffered property to true for any components that should use double-buffered drawing.


1 Answers

Set this code in your form. It will remove the flicker

 protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x02000000;

                return cp;
            }
        }

Hope it helps

like image 166
Marshal Avatar answered Sep 30 '22 12:09

Marshal