为什么 DataGridView 上的 DoubleBuffered 属性默认为 false 以及为什么它受到保护?

发布于 2024-07-07 20:14:59 字数 286 浏览 12 评论 0原文

我们遇到了 DataGridViews 的性能问题,重绘速度非常慢,并找到了解决方案 此处 创建派生类型并在控件上启用双缓冲。 (派生类型是必要的,因为 DoubleBuffered 属性受到保护)

将 DoubleBuffered 属性设置为 true 似乎没有任何缺点。

We had a performance issue with DataGridViews where the redraw was horridly slow and found the solution Here to create a derived type and enable double buffering on the control.
(Derived type is necessary since the DoubleBuffered property is protected)

It doesn't seem like there's any drawback to having the DoubleBuffered property set to true.

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

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

发布评论

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

评论(4

池予 2024-07-14 20:14:59

我认为最好的解决方案:

typeof(DataGridView).InvokeMember(
   "DoubleBuffered", 
   BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty,
   null, 
   myDataGridViewObject, 
   new object[] { true });

在这里找到

I think its best solution:

typeof(DataGridView).InvokeMember(
   "DoubleBuffered", 
   BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty,
   null, 
   myDataGridViewObject, 
   new object[] { true });

found here

浮光之海 2024-07-14 20:14:59

它受到保护是因为 DGV 继承了 Control 的属性。 并且 Control.DoubleBuffered 受到保护。 这是有道理的,因为每个派生控件都应该自行决定打开它。 而且控制用户随意打开或关闭它是没有意义的。 DGV 设计师决定放弃。

他们可能做出这一决定的原因之一是双缓冲实际上会使绘制速度变慢。 渲染缓冲区位图的额外步骤会花费时间。 它只是人眼看起来更快,您会观察到位图突然出现。 您无法看到绘制位图所需的时间。 除非其他控件需要绘制并且它们在 DGV 之后轮到它们,否则它是相当明显的。

您看到的是首先绘制的窗体,控件所在的位置有孔。 这些孔有白色背景。 当您使用 TransparencyKey 或 Opacity 属性时为黑色。 然后每个控件都会获取 Paint 事件,并将漏洞一一填充。 这种效果也被用户视为闪烁,尽管它与 DoubleBuffered 解决的闪烁是不同类型的。 当背景为黑色时尤其明显。

解决这个问题需要的是整个窗体及其所有控件都是双缓冲的。 这在 Windows 窗体中不可用。 然而,Windows XP 和更高版本实际上支持这一点,他们称之为“合成”。 将此代码复制/粘贴到表单类中的任意位置:

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

It is protected because DGV inherits the property from Control. And Control.DoubleBuffered is protected. Which makes sense because each derived control should decide for itself to turn that on. And it doesn't make sense for the control user to arbitrarily turn it on or off. The DGV designers decided for off.

One reason they might have decided that is that double buffering actually makes painting slower. The extra step to render the buffer bitmap costs time. It just looks faster to the human eye, you observe the bitmap suddenly appearing. You can't see the time it takes to draw into the bitmap. Unless other controls need to be painted and they get their turn after the DGV, then it is quite visible.

What you see is the form getting drawn first, with holes where the controls go. Those holes have a white background. Black when you use the TransparencyKey or Opacity property. Each control then gets the Paint event and the holes are filled one-by-one. That effect is perceived as flicker too by the user, although it is a different kind of flicker from the one that DoubleBuffered solves. It is especially noticeable when the background is black.

What's needed to solve this problem is that the entire form, with all its controls, is double-buffered. That's not available in Windows Forms. However, Windows XP and later actually support this, they called it "compositing". Copy/paste this code anywhere in the form class:

protected override CreateParams CreateParams {
    get {
        CreateParams cp = base.CreateParams;
        cp.ExStyle |= 0x02000000;  // Turn on WS_EX_COMPOSITED
        return cp;
    }
}
梦魇绽荼蘼 2024-07-14 20:14:59

根据定义,双缓冲使用两个缓冲区和两倍的内存来渲染控件的视图。 因此,这存在一些缺点,但是,考虑到现在 PC 中的内存量,可能没有多少人会注意到这种牺牲。

不知道为什么它受到保护。 也许该功能在该控件的早期版本中不可用,并且当它被引入时,设计者不想改变该控件的公共接口。 或者,也许他们认为这是一项高级功能,并希望限制刚接触该控件的人必须了解的方法数量,才能使其做一些有用的事情。

Double buffering by definition uses two buffers and twice the memory for rendering the view of the control into. So, there is some drawback there, however, with the amount of memory you get in a PC now, not many people probably would notice the sacrifice.

No idea why its protected. Maybe the function wasn't available in an early version of the control, and when it was introduced the designers didn't want to change the public interface of the control. Or perhaps they considered it to be an advanced feature and wanted to limit the number of methods someone new to the control would have to grok to be able to make it do something useful.

痴情换悲伤 2024-07-14 20:14:59

在 datagridview 上打开双缓冲不需要继承。 您可以通过对现有 datagridview 的反射来完成此操作。

Inheritance is not needed to turn on doublebuffering on a datagridview. You can do it with reflection on an existing datagridview.

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