如何在遭受闪烁的表单上设置控件的受保护DoubleBuffered属性?

===============>>#1 票数:85 已采纳

这是Dummy解决方案的更通用版本。

我们可以使用反射来获取受保护的DoubleBuffered属性,然后可以将其设置为true

注意如果用户在终端服务会话中运行 (例如远程桌面),则应支付开发者税,而不是使用双缓冲。如果此人在远程桌面上运行,则此助手方法不会启用双缓冲。

public static void SetDoubleBuffered(System.Windows.Forms.Control c)
{
   //Taxes: Remote Desktop Connection and painting
   //http://blogs.msdn.com/oldnewthing/archive/2006/01/03/508694.aspx
   if (System.Windows.Forms.SystemInformation.TerminalServerSession)
      return;

   System.Reflection.PropertyInfo aProp = 
         typeof(System.Windows.Forms.Control).GetProperty(
               "DoubleBuffered", 
               System.Reflection.BindingFlags.NonPublic | 
               System.Reflection.BindingFlags.Instance);

   aProp.SetValue(c, true, null); 
}

===============>>#2 票数:65

检查这个帖子

重复该答案的核心,您可以打开窗口上的WS_EX_COMPOSITED样式标志,以使表单及其所有控件双重缓冲。 样式标志自XP起可用。 它不会使绘画更快,但是整个窗口都是在屏幕外缓冲区中绘制的,并且在一次打击中对屏幕进行了打开。 使用户的眼睛立即看起来没有可见的绘画工件。 它并非完全没有问题,一些视觉样式渲染器可能会出现问题,特别是当TabControl有太多标签时。 因人而异。

将此代码粘贴到表单类中:

protected override CreateParams CreateParams {
    get {
        var cp = base.CreateParams;
        cp.ExStyle |= 0x02000000;    // Turn on WS_EX_COMPOSITED
        return cp;
    } 
}

这种技术与Winform的双缓冲支持之间的最大区别在于Winform的版本仅适用于一个控件。 您仍然可以看到每个控制油漆本身。 这也可能看起来像一个闪烁效果,特别是如果未上漆的控制矩形与窗口的背景形成鲜明对比。

===============>>#3 票数:18

System.Reflection.PropertyInfo aProp = typeof(System.Windows.Forms.Control)
    .GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic |
    System.Reflection.BindingFlags.Instance);
aProp.SetValue(ListView1, true, null);

Ian有关于在终端服务器上使用它的更多信息。

===============>>#4 票数:12

public void EnableDoubleBuffering()
{
   this.SetStyle(ControlStyles.DoubleBuffer | 
      ControlStyles.UserPaint | 
      ControlStyles.AllPaintingInWmPaint,
      true);
   this.UpdateStyles();
}

===============>>#5 票数:8

一种方法是扩展您想要双缓冲区的特定控件,并在控件的ctor中设置DoubleBuffered属性。

例如:

class Foo : Panel
{
    public Foo() { DoubleBuffered = true; }
}

===============>>#6 票数:5

用于打开或关闭控件的双缓冲的扩展方法

public static class ControlExtentions
{
    /// <summary>
    /// Turn on or off control double buffering (Dirty hack!)
    /// </summary>
    /// <param name="control">Control to operate</param>
    /// <param name="setting">true to turn on double buffering</param>
    public static void MakeDoubleBuffered(this Control control, bool setting)
    {
        Type controlType = control.GetType();
        PropertyInfo pi = controlType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
        pi.SetValue(control, setting, null);
    }
}

用法(例如如何使DataGridView DoubleBuffered):

DataGridView _grid = new DataGridView();
//  ...
_grid.MakeDoubleBuffered(true);

===============>>#7 票数:5

nobugz在他的链接中得到了方法的功劳,我只是重新发布。 将此覆盖添加到窗体:

protected override CreateParams CreateParams
{
    get
    {
        CreateParams cp = base.CreateParams;
        cp.ExStyle |= 0x02000000;
        return cp;
    }
}

这对我来说效果最好,在Windows 7上,当我调整控件重型窗口时,我出现了大的黑色块。 控制现在反弹! 但它更好。

===============>>#8 票数:4

这让我在第三方控制的情况下连续两天感到非常悲伤,直到我追踪它为止。

protected override CreateParams CreateParams
{
    get
    {
        CreateParams cp = base.CreateParams;
        cp.ExStyle |= 0x02000000;
        return cp;
    }
}

在重新调整/重新绘制包含其他几个控件的控件时,我最近有很多漏洞(粪便)。

我尝试了WS_EX_COMPOSITED和WM_SETREDRAW但是在我使用它之前没有任何工作:

private void myPanel_SizeChanged(object sender, EventArgs e)
{
     Application.DoEvents();
}

只是想传递它。

===============>>#9 票数:4

在尝试双缓冲之前,看看SuspendLayout()/ ResumeLayout()是否解决了您的问题。

===============>>#10 票数:2

这个精细解决方案的vb.net版本....:

Protected Overrides ReadOnly Property CreateParams() As CreateParams
    Get
        Dim cp As CreateParams = MyBase.CreateParams
        cp.ExStyle = cp.ExStyle Or &H2000000
        Return cp
    End Get
End Property

===============>>#11 票数:1

您还可以将控件继承到自己的类中,并在其中设置属性。 如果你倾向于在所有控件上做很多相同的设置,这个方法也很好。

===============>>#12 票数:0

我发现只需在表单上设置DoubleBuffered设置就会自动设置此处列出的所有属性。

  ask by Ian Boyd translate from so

未解决问题?本站智能推荐:

6回复

尽管有双重缓冲,但置顶器仍然闪烁

有谁知道如何摆脱闪烁? 我在SO,Web上进行了研究,并尝试了许多不同的方法,例如在不使用OnPaint()绘制时将TickerControl放入双缓冲Panel和la Double Buffering中:为什么它不起作用? 等等。 它仍然闪烁,不是每次都重新绘制,而是每秒闪烁两次。
5回复

如何双重缓冲面板?

我有一个面板上有一个轮盘赌轮,我需要双重缓冲面板,以便它停止闪烁。 谁能帮我吗? 编辑: 是的,我试过了。 panel1.doublebuffered不存在,只有this.doublebuffered。 而且我不需要缓冲表单,只需要Panel。
1回复

双重缓冲控制导致灰色出现

我有一个接受Control并向其绘制生成的图像的类。 在我的应用程序代码中,我为此使用了Panel控件-看起来工作良好,除了在重新绘制图像时控件上出现了很多闪烁之外。 我认为解决方案是在控件上启用双缓冲。 我正在使用以下代码进行此操作: 添加此代码后,将绘制图像,然后立即将其替换为
1回复

自定义控件中的双缓冲子控件(C#)

我想双缓冲包含按钮的自定义控件。 我已经尝试了各种方法来双重缓冲控件; SetStyle,BufferedGraphicsContext和绘制到位图。 这些都适用于控件的自定义绘图,但它们都不会处理将按钮绘制到后台缓冲区。 我该如何实现这一目标?
2回复

如何在Windows窗体StatusBar上启用双缓冲?

有没有一种方法可以在Windows Forms StatusBar类上启用双重缓冲? 我在鼠标移动事件上更新了一些地图坐标,并且闪烁/重新绘制非常明显。 我试过从StatusBar类继承并设置其DoubleBuffer = true并覆盖其OnPaintBackground方法。 我也
2回复

DrawReversibleLine()和双缓冲

我正在使用curstom双缓冲,并想使用DrawReversibleLine()绘制橡皮筋线。 但是,这怎么办呢? 此方法直接在屏幕上绘制,因此我看不到如何在后台缓冲区上绘制。 你会怎么做?
1回复

Winforms双缓冲

我将此添加到窗体的构造函数代码中: 但是,当加载控件时,无论控件何时更改(窗体及其组件经常更改(需要更新)),它仍然显示难看的工件。 我需要做些什么?
4回复

双缓冲ListBox

我有一个CheckedListBox(WinForms)控件(它继承自ListBox; googling显示问题在于ListBox),它被锚定到其表单的所有四个边。 调整窗体大小时,ListBox有一个丑陋的闪烁。 我尝试继承CheckedListBox并在ctor DoubleBuffer
2回复

我为什么要做手动双缓冲?

我正在开发一个C#游戏(2.0或3.5还没有决定)。 游戏将在具有六边形网格的地图上播放。 我很欣赏这个地图的UI应该使用双缓冲(很多层,所以慢绘图)。 我知道我可以通过样式启用双缓冲,或者创建我自己的缓冲区并自己处理它。 我在网上找到的大多数建议都是自己处理。 我想知道为什么? 显
3回复

使用C#进行双缓冲会产生负面影响

我编写了以下简单程序,它每100毫秒在屏幕上绘制一行(由timer1触发)。 我注意到绘图有点闪烁(也就是说,窗口并不总是完全是蓝色的,但是有些灰色闪耀)。 所以我的想法是使用双缓冲。 但是当我这样做时,情况变得更糟。 现在屏幕几乎总是灰色的,只是偶尔会出现蓝色(由timer2演示,每2