2010-04-02 62 views
2

我写了下面这个简单的程序,它每隔100毫秒在屏幕上绘制一行(由timer1触发)。我注意到图画闪烁了一点(也就是说,窗口并不总是完全蓝色,但有些灰色照耀着)。所以我的想法是使用双缓冲。但是当我这样做时,情况就更糟了。现在屏幕几乎总是灰色的,并且偶尔会出现蓝色(由timer2演示,每2000毫秒切换DoubleBuffered属性)。使用C#进行双缓冲具有负面影响

对此有何解释?

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

namespace WindowsFormsApplication1 { 
    public partial class Form1 : Form { 
     public Form1() { 
      InitializeComponent(); 
     } 

     private void Form1_Paint(object sender, PaintEventArgs e) { 
      Graphics g = CreateGraphics(); 
      Pen pen = new Pen(Color.Blue, 1.0f); 
      Random rnd = new Random(); 
      for (int i = 0; i < Height; i++) 
       g.DrawLine(pen, 0, i, Width, i); 
     } 

     // every 100 ms 
     private void timer1_Tick(object sender, EventArgs e) { 
      Invalidate(); 
     } 

     // every 2000 ms 
     private void timer2_Tick(object sender, EventArgs e) { 
      DoubleBuffered = !DoubleBuffered; 
      this.Text = DoubleBuffered ? "yes" : "no"; 
     } 
    } 
} 

回答

2

不需要使用多个缓冲区或位图对象或任何东西。

为什么不使用Paint事件提供的Graphics对象?像这样:

private void Form1_Paint(object sender, PaintEventArgs e) 
{ 
    Graphics g = e.Graphics; 
    Pen pen = new Pen(Color.Blue, 1.0f); 
    Random rnd = new Random(); 
    for (int i = 0; i < Height; i++) 
     g.DrawLine(pen, 0, i, Width, i); 
} 
+0

是的,你是对的。那是我答案的第二部分。 – 2010-04-02 11:49:31

+0

它很简单,它的工作原理。谢谢。 – 2010-04-02 12:06:50

2

尝试在测试时将构造函数中的double buffered属性设置为true。

您需要使用后台缓冲区。试试这个:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 

namespace DoubleBufferTest 
{ 
    public partial class Form1 : Form 
    { 
     private BufferedGraphicsContext context; 
     private BufferedGraphics grafx; 

     public Form1() 
     { 
      InitializeComponent(); 

      this.Resize += new EventHandler(this.OnResize); 
      DoubleBuffered = true; 

      // Retrieves the BufferedGraphicsContext for the 
      // current application domain. 
      context = BufferedGraphicsManager.Current; 

      UpdateBuffer(); 
     } 

     private void timer1_Tick(object sender, EventArgs e) 
     { 
      this.Refresh(); 

     } 

     private void OnResize(object sender, EventArgs e) 
     { 
      UpdateBuffer(); 
      this.Refresh(); 
     } 

     private void UpdateBuffer() 
     { 
      // Sets the maximum size for the primary graphics buffer 
      // of the buffered graphics context for the application 
      // domain. Any allocation requests for a buffer larger 
      // than this will create a temporary buffered graphics 
      // context to host the graphics buffer. 
      context.MaximumBuffer = new Size(this.Width + 1, this.Height + 1); 

      // Allocates a graphics buffer the size of this form 
      // using the pixel format of the Graphics created by 
      // the Form.CreateGraphics() method, which returns a 
      // Graphics object that matches the pixel format of the form. 
      grafx = context.Allocate(this.CreateGraphics(), 
       new Rectangle(0, 0, this.Width, this.Height)); 

      // Draw the first frame to the buffer. 
      DrawToBuffer(grafx.Graphics); 
     } 

     protected override void OnPaint(PaintEventArgs e) 
     { 
      grafx.Render(e.Graphics); 
     } 

     private void DrawToBuffer(Graphics g) 
     { 
      //Graphics g = grafx.Graphics; 
      Pen pen = new Pen(Color.Blue, 1.0f); 
      //Random rnd = new Random(); 
      for (int i = 0; i < Height; i++) 
       g.DrawLine(pen, 0, i, Width, i); 
     } 
    } 
} 

这是一个稍微破解版本的a double buffering example on MSDN

+0

我已经这样做了,效果相同。周期性切换只是为了更清楚地显示效果。 – 2010-04-02 10:32:22

5

我只是将所有的项目都绘制到自己的缓冲区中,然后一次全部复制。我用这个在许多应用中的图形,并一贯致力于对我非常好:

public Form1() 
    { 
     InitializeComponent(); 
    } 
    private void timer1_Tick(object sender, EventArgs e) 
    { 
     Invalidate();// every 100 ms 
    } 
    private void Form1_Load(object sender, EventArgs e) 
    { 
     DoubleBuffered = true; 
    } 
    private void Form1_Paint(object sender, PaintEventArgs e) 
    { 
     Bitmap buffer = new Bitmap(Width, Height); 
     Graphics g = Graphics.FromImage(buffer); 
     Pen pen = new Pen(Color.Blue, 1.0f); 
     //Random rnd = new Random(); 
     for (int i = 0; i < Height; i++) 
      g.DrawLine(pen, 0, i, Width, i); 
     BackgroundImage = buffer; 
    } 

编辑:经过进一步调查,它看起来像你的问题是你设置你的Graphics对象于:

Graphics g = CreateGraphics(); 

需求是:

Graphics g = e.Graphics(); 

所以你的问题可以通过创建像手工缓冲来解决我在上面做了,或者干脆改变你的图形对象。我测试了两个,他们都工作。