在没有闪烁的情况下在双缓冲控件上重新绘制图像时出现问题

时间:2009-02-04 16:32:10

标签: c# drawing doublebuffered

我知道双缓冲是一个经常谈论的主题,但无论我搜索多少并尝试不同的方法,我仍然无法控制重新绘制自己没有闪烁。这是我的代码:

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

    }
}

有什么想法吗?

5 个答案:

答案 0 :(得分:2)

天哪啊......

就像我在评论中所说的那样,pictureBox包含在另一个我没有编写的控件中(但是有源代码)。事实证明,闪烁是由这两行引起的:

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

我认为那是因为PictureBox实际上停靠在父控件中......

任何方式,感谢您的所有回复。

答案 1 :(得分:2)

您使用的是.Net 2.0吗?如果是这样的话,我发现以下的windows样式可以解决问题,即使嵌入了旧的固定Win32控件,它也很快!

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

确保始终从WM_PAINT消息中绘制,否则它将闪烁。 你不需要任何其他东西,一切都是自动的。

答案 2 :(得分:0)

您是否尝试将控件DoubleBuffered属性设置为true?

答案 3 :(得分:0)

父控件(Form?)中的绘画是否也是双缓冲的?

您的自定义控件可能会在没有闪烁的情况下进行绘制,但是当父控件被绘制并且不是双缓冲时,它会闪烁。

你可能会对错误的东西进行双重缓冲。

答案 4 :(得分:0)

我认为问题在于你的OnPaint方法from MSDN,当你调用ManagedBackBuffer.Render方法时,你应该传递CreateGraphics()而不是Graphics属性: