面板的双缓冲

4
通过将 "AllPaintingInWmPaint"、"UserPaint" 和 "DoubleBuffer" ControlStyles 的值设置为 "true" (this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true)),可以对整个窗体进行双缓冲处理。
但是,由于 System.Windows.Forms.Panel 类不允许这样做,因此无法实现。我找到了一种解决方案:http://bytes.com/topic/c-sharp/answers/267635-double-buffering-panel-control。我也尝试过这个:Winforms Double Buffering。即使在绘制小的图形时,它也会出现延迟问题。我在表单中使用了一些自定义资源和其他东西,因此不会将整个表单转换为一个绘图。而第二种方法似乎会引起问题。是否还有其他方法可行呢?
我之所以问这个问题,是因为我不希望在调整窗体大小时,面板上的图形一直闪烁。如果有一种不需要双缓冲就能消除闪烁的方法,我会很高兴知道。

我认为这取决于你想做什么。你是想刷新数据还是进行动画?还是你想制作一个游戏?我记得使用system.drawing很难消除闪烁,即使使用双缓冲(有时即使双缓冲帧率很慢,看起来也像闪烁)。 - keithwill
这是一个在WinForms窗口中进行的游戏。绘画是在面板上完成的。当用户单击面板时,绘画会发生变化。但是在滚动和调整大小过程中,也会出现闪烁问题。 - AlexSavAlexandrov
你可以在这里找到解决方案,它对我有效。解决方案 - Ahmed Yossef
3个回答

11

如果您不需要滚动支持,可以使用PictureBox,因为它默认是双缓冲的。如果需要一个双缓冲的可滚动面板,则很容易实现:

using System;
using System.Windows.Forms;

class MyPanel : Panel {
    public MyPanel() {
        this.DoubleBuffered = true;
        this.ResizeRedraw = true;
    }
}

使用ResizeRedraw选项可以禁止容器控件的绘画优化。如果你在面板中进行任何绘制操作,你将需要此选项。如果没有它,在调整面板大小时会导致绘画模糊。

双缓冲实际上会使绘画速度变慢。这可能会对后绘制的控件产生影响。在被填充之前留下的空洞可能会一段时间内可见,也被感知为闪烁。你可以在这个答案中找到对抗这种效果的对策。


我可以尝试去除一些控件,但它们不会很多...我会尝试创建一个新的 Panel 类,并“解锁”一些 System.Windows.Forms.Panel 的功能。但感谢您提供的链接。这是一个方便的教程。 - AlexSavAlexandrov
Hans,你怎么用这个新的面板替换旧的面板?我写了这个类,现在该怎么将它连接到我的现有“panel1”上,以便它获得上述属性? - Romy
从您的表单中删除panel1,并将此面板放置在其位置。您可以将其重命名为“panel1”,以使现有代码继续工作。 - Hans Passant
我已经尝试过了,但是在“panel1”之间出现了歧义错误。 - Romy

3

我应该很久以前就发布了我的解决方案……

好的,这是我的解决方案:

Bitmap buffer = new Bitmap(screenWidth, screenHeight);//set the size of the image
System.Drawing.Graphics gfx = Graphics.FromImage(buffer);//set the graphics to draw on the image
drawStuffWithGraphicsObject(gfx);//draw
pictureBox1.Image = buffer;//set the PictureBox's image to be the buffer

让我感到很蠢,在提出这个问题几年后才发现这个解决方案。
我尝试使用Panel,但是在应用新图像时速度变慢。在某个地方我读到,使用Panel比PictureBox更好。不过,我不知道是否需要在代码中添加一些东西来加速Panel的速度。

1
如果可以接受的话,您可以在调整大小时停止刷新面板,并在之后重新启用它,这样就可以摆脱难看的闪烁了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接