无闪烁的绘画 [英] Flicker-free painting

查看:76
本文介绍了无闪烁的绘画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这个论坛上经常听到的抱怨是Windows Forms导致"闪烁"的倾向。在有很多控件的表单上。这种闪烁有两个原因:

1。当需要绘制控件时,Windows会向控件发送两条消息。第一个(WM_ERASEBKGND)导致背景被绘制(OnPaintBackground),第二个导致前景被绘制(WM_PAINT,触发OnPaint)。看到首先绘制的背景,当绘图缓慢时前景是明显的。 Windows Forms为ControlStyles.OptimizedDoubleBuffer提供了这种闪烁的现成解决方案。搜索结果2。具有大量控件的表单需要很长时间才能绘制。特别是Button控件的默认样式很昂贵。一旦你获得超过50个控件,它就会开始变得明显。 Form类首先绘制其背景并留下"孔"。需要控制的地方。使用"不透明度"或"透明度"属性时,这些孔通常为白色,黑色。然后每个控件都被涂漆,填入孔中。视觉效果很难看,在Windows窗体中没有现成的解决方案。双缓冲无法解决它,因为它只适用于单个控件,而不适用于复合控件集。

我在SDK头文件中发现了一种新的Windows样式,可用于Windows XP和(可能)Vista:WS_EX_COMPOSITED。在为您的表单打开该样式后,Windows XP会对表单及其所有子控件执行双缓冲。这有效地解决了闪烁的第二个原因。这是一个例子:

使用System;
使用System.Drawing;使用System.Windows.Forms;

命名空间WindowsApplication1 {
public partial class Form1:Form {
public Form1(){
InitializeComponent();
for(int ix = 0; ix< 30; ++ ix){
for(int iy = 0; iy< 30; ++ iy){
Button btn = new Button() ;
btn.Location = new Point(ix * 10,iy * 10);
this.Controls.Add(btn);


}

受保护的覆盖CreateParams CreateParams {
get {
CreateParams cp = base.CreateParams;
cp.ExStyle | = 0x02000000;
return cp;


}





要在工作中查看它,请最小化并恢复表单并观察其绘制行为。注释cp.ExStyle分配以查看差异。要以自己的形式使用它,只需复制并粘贴CreateParams属性即可。

有些警告:这不会加快绘画速度。在绘画过程中,您的表单会保持不可见,然后在完成后弹出屏幕。当您使用Opacity或TransparencyKey属性时,它不起作用,在进行绘画时,表单轮廓将显示为丑陋的黑色矩形。对此最好的解决方案是使用计时器将不透明度值增加到99%,以使图形在绘制后可见。

我还没有对此进行大量尝试,如果您在使用它时遇到问题,请发布到此主题。

解决方案

< blockquote>在.NET framework 2.0下你可以简单地使用

类Form1:Form {
Form1(){
this.doublebuffered = true;
}



A frequently heard complaint at this forum is Windows Forms' tendency to cause "flicker" on forms with a lot of controls.  There are two causes for this kind of flicker:

1. Windows sends a control two messages when a control needs to be painted.  The first one (WM_ERASEBKGND) causes the background to be painted (OnPaintBackground), the second causes the foreground to be painted (WM_PAINT, firing OnPaint).  Seeing the background drawn first, then the foreground is noticeable when the drawing is slow.  Windows Forms has a ready solution for this kind of flicker with ControlStyles.OptimizedDoubleBuffer.

2. A form that has a lot of controls takes a long time to paint.  Especially the Button control in its default style is expensive.  Once you get over 50 controls, it starts getting noticeable.  The Form class paints its background first and leaves "holes" where the controls need to go.  Those holes are usually white, black when you use the Opacity or TransparencyKey property.  Then each control gets painted, filling in the holes.  The visual effect is ugly and there's no ready solution for it in Windows Forms.  Double-buffering can't solve it as it only works for a single control, not a composite set of controls.

I discovered a new Windows style in the SDK header files, available for Windows XP and (presumably) Vista: WS_EX_COMPOSITED.  With that style turned on for your form, Windows XP does double-buffering on the form and all its child controls.  This effectively solves the 2nd cause of flicker.  Here's an example:

using System;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsApplication1 {
  public partial class Form1 : Form {
    public Form1() {
      InitializeComponent();
      for (int ix = 0; ix < 30; ++ix) {
        for (int iy = 0; iy < 30; ++iy) {
          Button btn = new Button();
          btn.Location = new Point(ix*10, iy*10);
          this.Controls.Add(btn);
        }
      }
    }
    protected override CreateParams CreateParams {
      get {
        CreateParams cp = base.CreateParams;
        cp.ExStyle |= 0x02000000;
        return cp;
      }
    }
  }
}

To see it at work, minimize and restore the form and observe its painting behavior.  Comment the cp.ExStyle assignment to see the difference.  All you have to do to use this in your own form is to copy and paste the CreateParams property.

Some caveats with this: this doesn't speed up the painting.  Your form just stays invisible while painting is taking place, then pops on the screen when it is done.  And it doesn't work when you use the Opacity or TransparencyKey property, the form outline will be visible as an ugly black rectangle while painting takes place.  The best solution for that is to use a timer to increment the Opacity value to 99% to make the form visible after it is painted.

I haven't experimented a great deal with this as yet, please post to this thread if you have problems using it.

解决方案

Under the .NET framework 2.0 you can simply use

class Form1 : Form {
  Form1(){
   this.doublebuffered = true;
  }
}


这篇关于无闪烁的绘画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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