everwicked
everwicked

Reputation:

Problems re-drawing an image on a double-buffered control without flickering

I know that double-buffering is an often-talked subject but no matter how much I searched and tried different approaches, I still can't get the control to re-draw itself without a flicker. Here's my code:

using System;
using System.Drawing;
using System.Windows.Forms;

namespace Emgu.UI
{
    public class DoubleBufferedPictureBox : Control
    {
        const BufferedGraphics NO_MANAGED_BACK_BUFFER = null;

        BufferedGraphicsContext GraphicManager;
        BufferedGraphics ManagedBackBuffer;

        public Bitmap Bitmap { get; set; }
        public Rectangle DrawRectangle { get; set; }

        public DoubleBufferedPictureBox()
        {
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);

            GraphicManager = BufferedGraphicsManager.Current;
            GraphicManager.MaximumBuffer =
                   new Size(Width + 1, Height + 1);
            ManagedBackBuffer =
                GraphicManager.Allocate(CreateGraphics(),
                                               ClientRectangle);

            Resize += DoubleBufferedPictureBox_Resize;
        }

        void DoubleBufferedPictureBox_Resize(object sender, EventArgs e)
        {
            if (ManagedBackBuffer != NO_MANAGED_BACK_BUFFER)
                ManagedBackBuffer.Dispose();

            GraphicManager.MaximumBuffer =
                  new Size(Width + 1, Height + 1);

            ManagedBackBuffer =
                GraphicManager.Allocate(CreateGraphics(),
                                                ClientRectangle);
            Refresh();
        }

        protected override void OnPaint(PaintEventArgs pe)
        {
            ManagedBackBuffer.Graphics.DrawImage(Bitmap, DrawRectangle);
            ManagedBackBuffer.Render(pe.Graphics);
        }

    }
}

Any ideas?

Upvotes: 1

Views: 3406

Answers (5)

Coincoin
Coincoin

Reputation: 28616

Are you using .Net 2.0 ? If so, I found that the following windows styles do the trick, even with old stuborn Win32 controls embeded, and it's fast too!

// Note the >>> Optimized <<< DoubleBuffer
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.UserPaint, true);

Make sure you always draw from inside a WM_PAINT message, else it will flicker. You don't need anything else, everything is automatic.

Upvotes: 2

everwicked
everwicked

Reputation:

Oh my God...

Like I said in my comments, the pictureBox is contained within another Control that I didn't write (but have the source to). It turns out that the flicker is caused by these two lines:

if (pictureBox.Width != _displayedImage.Width) pictureBox.Width = _displayedImage.Width;
if (pictureBox.Height != _displayedImage.Height) pictureBox.Height = _displayedImage.Height;

I think that's because the PictureBox is actually docked in the parent control...

Any way, thanks for all your responses.

Upvotes: 2

scottm
scottm

Reputation: 28699

I think the problem is in your OnPaint method, from MSDN, when you call your ManagedBackBuffer.Render method, you should pass CreateGraphics() not the Graphics property:

Upvotes: 0

arul
arul

Reputation: 14094

Is painting in the parent control(Form?) also double-buffered?

Your custom control may be painted without flicker but further when the parent control is painted and is not double-buffered, it's flickering.

You may be double-buffering the wrong thing.

Upvotes: 0

scottm
scottm

Reputation: 28699

Have you tried setting the controls DoubleBuffered property to true?

Upvotes: 0

Related Questions