Subscribe

RSS Feed (xml)

Use Double Buffering to Increase Redraw Speed

In some applications you need to repaint a form or control frequently. This is commonly the case when performing animation. For example, you might use a timer to invalidate your form every second. Your painting code could then redraw an image at a new location, creating the illusion of motion. The problem with this approach is that every time you invalidate the form, Windows repaints the window background (clearing the form) and then runs your painting code, which draws the graphic element by element. This can cause substantial on-screen flicker.

Double buffering is a technique you can implement to reduce this flicker. With double buffering, your drawing logic writes to an in-memory bitmap, which is copied to the form at the end of the drawing operation in a single, seamless repaint operation. Flickering is reduced dramatically.

The first step when implementing double buffering is to ensure that the form background isn't repainted automatically when the form is invalidated. This automatic clearing is the most significant cause of flicker because it replaces your image with a blank frame (if only for a fraction of a second). To prevent background painting, override the form's OnPaintBackground method so that it takes no action. The second step is to change the painting code so that it draws the image to an in-memory bitmap. When complete, the bitmap is copied to the form. This approach ensures that the refresh is a single repaint operation, and that time-consuming drawing logic won't cause additional flicker.

The following example shows an animation of an image (in this case, the Windows logo) alternately growing and shrinking on the page. The drawing logic is performed in the Form.Paint event handler, and a timer is used to invalidate the form every 10 milliseconds so that the image can be redrawn. The user can choose whether to enable double buffering through a check box on the form. Without double buffering, the form flickers noticeably. When double buffering is enabled, however, the image grows and shrinks with smooth, flicker-free animation.

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

public class DoubleBuffering : System.Windows.Forms.Form {

    private System.Windows.Forms.CheckBox chkUseDoubleBuffering;
    private System.Windows.Forms.Timer tmrRefresh;

    // (Designer code omitted.)

    // Track the image size, and the type of animation
    // (expanding or shrinking).
    private bool isShrinking = false;
    private int imageSize = 0;

    // Store the logo that will be painted on the form.
    private Image image;

    private void DoubleBuffering_Load(object sender, System.EventArgs e) {
    
        // Load the logo image from the file.
        image = Image.FromFile("image.bmp");

        // Start the timer that invalidates the form.
        tmrRefresh.Start();
    }

    private void tmrRefresh_Tick(object sender, System.EventArgs e) {
    
        // Change the desired image size according to the animation mode.            
        if (isShrinking) {
            imageSize--;

        }else {
            imageSize++;
        }

        // Change the sizing direction if it nears the form border.
        if (imageSize > (this.Width - 150)) {
            isShrinking = true;

        }else if (imageSize < 1) {
            isShrinking = false;
        }

        // Repaint the form.
        this.Invalidate();
    }

    private void DoubleBuffering_Paint(object sender, 
      System.Windows.Forms.PaintEventArgs e) {
    
        Graphics g;
        Bitmap drawing = null;

        if (chkUseDoubleBuffering.Checked) {
        
            // Double buffering is being used.
            // Create a new in-memory bitmap that represents the
            // form's surface.
            drawing = new Bitmap(this.Width, this.Height, e.Graphics);
            g = Graphics.FromImage(drawing);

        }else {
        
            // Double buffering is not being used.
            // Draw directly to the form.
            g = e.Graphics;
        }

        g.SmoothingMode = SmoothingMode.HighQuality;

        // Draw the background.
        g.FillRectangle(Brushes.Yellow, new Rectangle(new Point(0, 0),
        this.ClientSize));

        // Draw the logo image.
        g.DrawImage(image, 50, 50, 50 + imageSize, 50 + imageSize);

        // If using double buffering, copy the completed in-memory
        // bitmap to the form.
        if (chkUseDoubleBuffering.Checked) {
        
            e.Graphics.DrawImageUnscaled(drawing, 0, 0);
            g.Dispose();
        }
    }

    protected override void OnPaintBackground(
      System.Windows.Forms.PaintEventArgs pevent) {
  
        // Do nothing.
    }
}

Technorati :

No comments:

Post a Comment

Archives

LocalsAdda.com-Variety In Web World

Fun Mail - Fun in the Mail