不是双缓冲可以解决的那种闪烁。也不是 BeginUpdate 或 SuspendLayout。你有太多的控件,BackgroundImage 可以使它成为lot worse.
它在 UserControl 绘制自身时启动。它绘制背景图像,在子控件窗口所在的位置留下孔。然后,每个子控件都会收到一条消息来绘制自己,它们将用窗口内容填充该孔。当您有很多控件时,用户会在一段时间内看到这些漏洞。它们通常是白色的,在黑暗时与背景图像形成鲜明对比。或者,如果表单设置了 Opacity 或 TransparencyKey 属性,它们可以是黑色的,与任何东西形成鲜明对比。
这是 Windows 窗体的一个非常基本的限制,它与 Windows 呈现窗口的方式有关。顺便说一句,由 WPF 修复,它不使用窗口作为子控件。您想要的是对整个表单(包括子控件)进行双缓冲。这是可能的,检查我的代码这个线程的解决方案。但它有副作用,并且实际上并没有提高绘画速度。代码很简单,将其粘贴到您的表单中(而不是用户控件):
protected override CreateParams CreateParams {
get {
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}
}
您可以采取多种措施来提高绘画速度,使闪烁不再明显。首先处理背景图像。他们可以really当源图像很大并且需要缩小以适应控件时,成本高昂。将BackgroundImageLayout 属性更改为“Tile”。如果这提供了明显的加速,请返回到您的绘画程序并调整图像大小,以更好地匹配典型的控件大小。或者在 UC 的 OnResize() 方法中编写代码来创建适当大小的图像副本,这样就不必在每次控件重绘时都调整其大小。对该副本使用 Format32bppPArgb 像素格式,它的渲染速度比任何其他像素格式快约 10 倍。
接下来您可以做的就是防止孔洞太明显并且与图像形成鲜明对比。你可以turn offUC 的 WS_CLIPCHILDREN 样式标志,该标志防止 UC 在子控件所在的区域进行绘制。将此代码粘贴到 UserControl 的代码中:
protected override CreateParams CreateParams {
get {
var parms = base.CreateParams;
parms.Style &= ~0x02000000; // Turn off WS_CLIPCHILDREN
return parms;
}
}
子控件现在将在背景图像的顶部绘制自己。你可能仍然会看到它们一张一张地画自己,但中间丑陋的白色或黑洞将不可见。
最后但并非最不重要的一点是,减少子控件的数量始终是解决缓慢绘制问题的好方法。覆盖 UC 的 OnPaint() 事件并绘制现在在子项中显示的内容。特定的 Label 和 PictureBox 是very浪费。方便点击,但其轻量级替代方案(绘制字符串或图像)仅需要 OnPaint() 方法中的一行代码。