Mar*_*ini 26 c# performance gdi+ doublebuffered winforms
我有一些库"自定义控件".基本上我们有自己的按钮,圆角板和一些带有一些定制油漆的组合箱.尽管OnPaint方法中存在"数学",但控件非常标准.大多数情况下,我们所做的只是绘制圆角并为背景添加渐变.我们使用GDI +来实现这一切.
这些控件都可以(根据我们的客户非常好看),但是尽管有DoubleBuffer,你可以看到一些重绘,特别是当同一个表格上有20个++按钮时(例如).在表单加载时,您会看到绘制的按钮...这很烦人.
我很确定我们的按钮不是地球上最快的东西,但我的问题是:如果双缓冲区"打开",那么不应该在后台进行所有重绘,而Windows子系统应该"立即"显示结果吗?
另一方面,如果存在将创建标签的"复杂"foreach循环,则将它们添加到面板(双缓冲)并更改其属性,如果我们在循环之前挂起面板并在循环时恢复面板布局结束,不应该所有这些控件(标签和按钮)"几乎立即"出现?这不会发生这种情况,您可以看到面板被填充.
知道为什么不发生这种情况吗?我知道很难在没有示例代码的情况下进行评估,但这也难以复制.我可以用相机制作一个视频,但相信我这个,它不是很快:)
Jud*_*ngo 12
我们也看到了这个问题.
我们已经看到"修复"它的一种方法是完全暂停控制的绘制,直到我们准备好去.为此,我们将WM_SETREDRAW消息发送到控件:
// Note that WM_SetRedraw = 0XB
// Suspend drawing.
UnsafeSharedNativeMethods.SendMessage(handle, WindowMessages.WM_SETREDRAW, IntPtr.Zero, IntPtr.Zero);
...
// Resume drawing.
UnsafeSharedNativeMethods.SendMessage(handle, WindowMessages.WM_SETREDRAW, new IntPtr(1), IntPtr.Zero);
Run Code Online (Sandbox Code Playgroud)
小智 11
您应该注意的一件事是您是否在面板的任何子控件上设置了BackColor = Transparent.BackColor = Transparent将显着降低渲染性能,尤其是在父面板使用渐变时.
Windows窗体不使用真正的透明度,而是使用"假的".每个子控件绘制调用都会在父级上生成绘制调用,因此父级可以绘制其子控件绘制其内容的背景,使其显示为透明.
因此,如果您有50个子控件,将在父控件上生成额外的50个绘制调用以进行背景绘制.由于渐变通常较慢,因此性能会下降.
希望这可以帮助.
我会从性能角度来解决你的问题.
foreach循环将创建标签,将它们添加到面板(双缓冲)并更改其属性
如果这是订单的完成,那么还有改进的余地.首先创建所有标签,更改其属性,并在它们准备就绪后,将它们添加到面板:Panel.Controls.AddRange(Control[])
大多数情况下,我们所做的只是绘制圆角并为背景添加渐变
你一遍又一遍地做同样的事吗?你的渐变是如何产生的?写一个图像不会那么慢.我曾经不得不在内存中创建一个1680x1050的渐变,而且速度非常快,比如太快了Stopwatch,因此绘制渐变不会那么难.
我的建议是尝试缓存一些东西.打开画图,绘制角落并保存到磁盘,或仅在内存中生成一次图像.然后根据需要加载(并调整大小).渐变相同.
即使不同的按钮具有不同的颜色,但具有相同的图案,您也可以使用Paint或其他任何东西创建位图,并在运行时加载它并将Color值乘以另一种颜色.
编辑:
如果我们在循环之前暂停布局面板并在循环结束时恢复面板的布局
这不是SuspendLayout和ResumeLayout的用途.它们暂停布局逻辑,即控件的自动定位.与FlowLayoutPanel和TableLayoutPanel最相关.
至于doublebuffering,我不确定它是否适用于自定义绘制代码(尚未尝试).我想你应该实现自己的.
简而言之,双重缓冲:
它非常简单,只需几行代码.在paint事件上,渲染到位图而不是渲染到Graphics对象,然后将该位图绘制到Graphics对象.
除了该DoubleBuffered属性之外,还可以尝试将其添加到控件的构造函数中:
SetStyle(ControlStyles.OptimizedDoubleBuffer |
ControlStyles.AllPaintingInWmPaint, true);
Run Code Online (Sandbox Code Playgroud)
如果这最终还不够(我会冒险说还不够),请考虑看看我对这个问题的回答,并暂停/恢复面板或表单的重绘。这将使您的布局操作完成,然后在完成后进行所有绘图。