在双缓冲控件上重新绘制图像而不闪烁时出现问题

发布于 2024-07-13 00:09:04 字数 1697 浏览 6 评论 0原文

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

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

    }
}

有什么想法吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

无名指的心愿 2024-07-20 00:09:04

天哪...

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

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

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

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

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.

痴者 2024-07-20 00:09:04

您使用的是.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 消息内部进行绘制,否则它将闪烁。
你不需要任何其他东西,一切都是自动的。

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.

请远离我 2024-07-20 00:09:04

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

Have you tried setting the controls DoubleBuffered property to true?

伊面 2024-07-20 00:09:04

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

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

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

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.

就是爱搞怪 2024-07-20 00:09:04

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:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文