Paint Event e.Graphics.DrawImage 似乎没有遵循双缓冲

Paint Event e.Graphics.DrawImage doesn't seem to follow double buffering

目前正在重写旧代码,其中我使用图形函数绘制基于位置数据的交互式矢量地图。

回到使用 .NET 4.7 时,我可以简单地将我的东西绘制到位图中,执行 Graphics gr = Panel.CreateGraphics(),然后执行 gr.DrawImage()。我从来没有启用双缓冲,而且它总是工作正常。

现在我在 .NET 5 中,仍然使用 WinForms,并尝试根据 Paint 事件做一些更好的事情,并在与之交互时使组件无效。

这里是我问题的核心

Bitmap Buffer; //this is initialized elsewhere, don't worry

public void MapPlotPanel_Paint(object sender, PaintEventArgs e)
{
//... Drawing code removed, it's just a novel Graphics object drawing into the Bitmap ...
e.Graphics.DrawImage(Buffer, Point.Empty);
}

虽然这可以将图像很好地绘制到面板中,但我会出现可怕的闪烁,因为我可以实时看到位图被绘制到面板中。即使我 Panel.CreateGraphics() 在事件处理程序中使用它而不是 PaintEventArgs 对象,就像我之前所做的那样,同样的事情也会发生。

在表单加载事件处理程序中,我有

SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

没有效果。

不过,最糟糕的是,如果我不使用 Graphics 将图像应用于面板,而是 Panel.BackgroundImage = Buffer,它永远不会闪烁,当然,绘制的内容只会显示下一个组件失效的时间。

我真的想不出我在这里可能遗漏了什么,我们将不胜感激。

正如评论中已经提到的那样 - 要启用面板的双缓冲,您需要 SetStyle() 在面板构造函数中,而不是在表单加载事件中。为此,您必须创建自己的面板。下面是自定义面板的示例代码 class.

public partial class CustomPanel : UserControl
{
    public CustomPanel()
    {
        InitializeComponent();

        // Add Double Buffering
        SetStyle(ControlStyles.UserPaint | ControlStyles.ResizeRedraw | ControlStyles.DoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
    }
}