如何修复用户控件中的闪烁 [英] How to fix the flickering in User controls

查看:33
本文介绍了如何修复用户控件中的闪烁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的应用程序中,我不断地从一个控件移动到另一个控件.我创建了没有.用户控件,但在导航期间我的控件会闪烁.更新需要 1 或 2 秒.我试着设置这个

In my application i am constantly moving from one control to another. I have created no. of user controls, but during navigation my controls gets flicker. it takes 1 or 2 sec to update. I tried to set this

SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
or
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true); 
SetStyle(ControlStyles.DoubleBuffer, true);

但它没有帮助...每个控件都有相同的背景图像和不同的控件.那么有什么解决办法呢..
谢谢.

but it didn't help... Each control has same background image with different controls. So what is the solution for it..
Thanks.

推荐答案

不是双缓冲可以解决的那种闪烁.也不是 BeginUpdate 或 SuspendLayout.您的控件太多了,BackgroundImage 会使它很多变得更糟.

It is not the kind of flicker that double-buffering can solve. Nor BeginUpdate or SuspendLayout. You've got too many controls, the BackgroundImage can make it a lot worse.

它在 UserControl 绘制自身时开始.它绘制背景图像,在子控件窗口所在的位置留下孔.然后每个子控件都会收到一条消息来绘制自己,它们将用它们的窗口内容填充空洞.当您有很多控件时,用户会在一段时间内看到这些漏洞.它们通常是白色的,在黑暗时与背景图像形成鲜明对比.或者,如果表单设置了 Opacity 或 TransparencyKey 属性,则它们可能是黑色的,与几乎任何东西形成鲜明对比.

It starts when the UserControl paints itself. It draws the BackgroundImage, leaving holes where the child control windows go. Each child control then gets a message to paint itself, they'll fill in the hole with their window content. When you have a lot of controls, those holes are visible to the user for a while. They are normally white, contrasting badly with the BackgroundImage when it is dark. Or they can be black if the form has its Opacity or TransparencyKey property set, contrasting badly with just about anything.

这是 Windows 窗体的一个非常基本的限制,它与 Windows 呈现窗口的方式有关.顺便说一句,由 WPF 修复,它不使用窗口作为子控件.您想要的是对整个表单进行双缓冲,包括子控件.这是可能的,在 这个线程的解决方案.但是它有副作用,实际上并没有提高绘画速度.代码很简单,将其粘贴到您的表单中(不是用户控件):

This is a pretty fundamental limitation of Windows Forms, it is stuck with the way Windows renders windows. Fixed by WPF btw, it doesn't use windows for child controls. What you'd want is double-buffering the entire form, including the child controls. That's possible, check my code in this thread for the solution. It has side-effects though, and doesn't actually increase painting speed. The code is simple, paste this in your form (not the user control):

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

您可以采取许多措施来提高绘画速度,直至闪烁不再明显.首先处理背景图像.当源图像很大并且需要缩小以适应控件时,它们可能真的昂贵.将 BackgroundImageLayout 属性更改为平铺".如果这会带来明显的加速,请返回到您的绘画程序并调整图像大小以更好地匹配典型的控件大小.或者在 UC 的 OnResize() 方法中编写代码来创建一个适当大小的图像副本,这样就不必在每次控件重绘时都调整其大小.对该副本使用 Format32bppPArgb 像素格式,它的渲染速度比任何其他像素格式快 10 倍.

There are many things you can do to improve painting speed, to the point that the flicker isn't noticeable anymore. Start by tackling the BackgroundImage. They can be really expensive when the source image is large and needs to be shrunk to fit the control. Change the BackgroundImageLayout property to "Tile". If that gives a noticeable speed-up, go back to your painting program and resize the image to be a better match with the typical control size. Or write code in the UC's OnResize() method to create a properly sized copy of the image so that it doesn't have to be resized every time the control repaints. Use the Format32bppPArgb pixel format for that copy, it renders about 10 times faster than any other pixel format.

接下来您可以做的是防止孔太明显并与图像形成鲜明对比.您可以关闭UC 的 WS_CLIPCHILDREN 样式标志,该标志防止 UC 在子控件所在的区域进行绘画.将此代码粘贴到 UserControl 的代码中:

Next thing you can do is prevent the holes from being so noticeable and contrasting badly with the image. You can turn off the WS_CLIPCHILDREN style flag for the UC, the flag that prevents the UC from painting in the area where the child controls go. Paste this code in the UserControl's code:

protected override CreateParams CreateParams {
  get {
    var parms = base.CreateParams;
    parms.Style &= ~0x02000000;  // Turn off WS_CLIPCHILDREN
    return parms;
  }
}

子控件现在将自己绘制在背景图像的顶部.你可能仍然会看到它们一张一张地画自己,但是看不到中间的丑陋的白色或黑洞.

The child controls will now paint themselves on top of the background image. You might still see them painting themselves one by one, but the ugly intermediate white or black hole won't be visible.

最后但并非最不重要的一点是,减少子控件的数量始终是解决缓慢绘制问题的好方法.覆盖 UC 的 OnPaint() 事件并绘制现在显示在孩子身上的内容.特定的 Label 和 PictureBox 非常浪费.方便点击,但它们的轻量级替代方案(绘制字符串或图像)在您的 OnPaint() 方法中只需要一行代码.

Last but not least, reducing the number of child controls is always a good approach to solve slow painting problems. Override the UC's OnPaint() event and draw what is now shown in a child. Particular Label and PictureBox are very wasteful. Convenient for point and click but their light-weight alternative (drawing a string or an image) takes only a single line of code in your OnPaint() method.

这篇关于如何修复用户控件中的闪烁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆