1

我知道双缓冲是一个经常被谈论的主题,但无论我如何搜索和尝试不同的方法,我仍然无法让控件在没有闪烁的情况下重新绘制自身。这是我的代码:

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

    }
}

有任何想法吗?

4

5 回答 5

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 消息中绘制,否则它会闪烁。你不需要其他任何东西,一切都是自动的。

于 2009-02-04T22:17:14.280 回答
2

我的天啊...

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

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

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

无论如何,感谢您的所有回复。

于 2009-02-04T19:12:06.713 回答
0

Have you tried setting the controls DoubleBuffered property to true?

于 2009-02-04T16:43:00.570 回答
0

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

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

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

于 2009-02-04T17:02:07.287 回答
0

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

于 2009-02-04T17:11:03.680 回答