2010-04-02 78 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(); 

所以你的問題可以通過創建像手工緩衝來解決我在上面做了,或者乾脆改變你的圖形對象。我測試了兩個,他們都工作。