Export (0) Print
Expand All

BufferedGraphics Class

Provides a graphics buffer for double buffering.

Namespace: System.Drawing
Assembly: System.Drawing (in system.drawing.dll)

'Declaration
Public NotInheritable Class BufferedGraphics
	Implements IDisposable
'Usage
Dim instance As BufferedGraphics

public final class BufferedGraphics implements IDisposable
public final class BufferedGraphics implements IDisposable
Not applicable.

The BufferedGraphics class allows you to implement custom double buffering for your graphics. It provides a wrapper for a graphics buffer, along with methods that you can use to write to the buffer and render its contents to an output device.

Graphics that use double buffering can reduce or eliminate flicker that is caused by redrawing a display surface. When you use double buffering, updated graphics are first drawn to a buffer in memory, and the contents of this buffer are then quickly written to some or all of the displayed surface. This relatively brief overwrite of the displayed graphics typically reduces or eliminates the flicker that sometimes occurs when graphics are updated.

NoteNote:

The simplest way to use double buffering is to set the OptimizedDoubleBuffer control style flag on a control using the SetStyle method. Setting the OptimizedDoubleBuffer flag for a control redirects all painting for the control through a default graphics buffer, without requiring any additional code. This flag is set to true by default.

The BufferedGraphics class has no public constructor and must be created by the BufferedGraphicsContext for an application domain using its Allocate method. You can retrieve the BufferedGraphicsContext for the current application domain from the static BufferedGraphicsManager.Current property.

The Graphics property can be used for drawing to the graphics buffer. This property provides access to the Graphics object that draws to the graphics buffer allocated for this BufferedGraphics object.

The Render method with no arguments draws the contents of the graphics buffer to the surface specified when the buffer was allocated. Other overloads of the Render method allow you to specify a Graphics object or an IntPtr object that points to a device context to which to draw the contents of the graphics buffer.

For more information about drawing double-buffered graphics, see Double Buffered Graphics.

The following code example demonstrates using a BufferedGraphics object to draw graphics using several types of buffering implementations. Clicking the form alternately starts and stops a timer that causes draw updates. The draw updates allow you to observe the effect of double buffering. Right-clicking the form cycles through the following drawing modes:

  • Drawing directly to the Handle for a Form.

  • Drawing by overriding the OnPaint method using the OptimizedDoubleBuffer control style.

  • Drawing by overriding the OnPaint method for the form method without using the OptimizedDoubleBuffer control style.

In each mode, text is drawn that identifies the current mode and describes the behavior that occurs when each mouse button is pressed.

Imports System
Imports System.ComponentModel
Imports System.Drawing
Imports System.Windows.Forms

Public Class BufferingExample
    Inherits Form
    Private context As BufferedGraphicsContext
    Private grafx As BufferedGraphics
    
    Private bufferingMode As Byte
    Private bufferingModeStrings As String() = _
        {"Draw to Form without OptimizedDoubleBufferring control style", _
         "Draw to Form using OptimizedDoubleBuffering control style", _
         "Draw to HDC for form"}
    
    Private timer1 As System.Windows.Forms.Timer
    Private count As Byte    
    
    Public Sub New()
        ' Configure the Form for this example.
        Me.Text = "User double buffering"
        AddHandler Me.MouseDown, AddressOf Me.MouseDownHandler
        AddHandler Me.Resize, AddressOf Me.ResizeHandler
        Me.SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.UserPaint, True)
        
        ' Configure a timer to draw graphics updates.
        timer1 = New System.Windows.Forms.Timer()
        timer1.Interval = 200
        AddHandler timer1.Tick, AddressOf Me.OnTimer
        
        bufferingMode = 2
        count = 0
        
        ' Retrieves the BufferedGraphicsContext for the 
        ' current application domain.
        context = BufferedGraphicsManager.Current
        
        ' 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(Me.Width + 1, Me.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(Me.CreateGraphics(), _
            New Rectangle(0, 0, Me.Width, Me.Height))
        
        ' Draw the first frame to the buffer.
        DrawToBuffer(grafx.Graphics)
    End Sub    
    
    Private Sub MouseDownHandler(sender As Object, e As MouseEventArgs)
        If e.Button = MouseButtons.Right Then
            ' Cycle the buffering mode.
            bufferingMode = bufferingMode+1
            If bufferingMode > 2 Then
                bufferingMode = 0
            End If 
            ' If the previous buffering mode used 
            ' the OptimizedDoubleBuffering ControlStyle,
            ' disable the control style.
            If bufferingMode = 1 Then
                Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
            End If 
            ' If the current buffering mode uses
            ' the OptimizedDoubleBuffering ControlStyle,
            ' enabke the control style.
            If bufferingMode = 2 Then
                Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, False)
            End If 
            ' Cause the background to be cleared and redraw.
            count = 6
            DrawToBuffer(grafx.Graphics)
            Me.Refresh()
        Else
            ' Toggle whether the redraw timer is active.
            If timer1.Enabled Then
                timer1.Stop()
            Else
                timer1.Start()
            End If
        End If
    End Sub
     
    Private Sub OnTimer(sender As Object, e As EventArgs)
        ' Draw randomly positioned ellipses to the buffer.
        DrawToBuffer(grafx.Graphics)
        
        ' If in bufferingMode 2, draw to the form's HDC.
        If bufferingMode = 2 Then
            ' Render the graphics buffer to the form's HDC.
            grafx.Render(Graphics.FromHwnd(Me.Handle))
        ' If in bufferingMode 0 or 1, draw in the paint method.
        Else
            Me.Refresh()
        End If
    End Sub
     
    Private Sub ResizeHandler(sender As Object, e As EventArgs)
        ' Re-create the graphics buffer for a new window size.
        context.MaximumBuffer = New Size(Me.Width + 1, Me.Height + 1)
        If (grafx IsNot Nothing) Then
            grafx.Dispose()
            grafx = Nothing
        End If
        grafx = context.Allocate(Me.CreateGraphics(), New Rectangle(0, 0, Me.Width, Me.Height))
        
        ' Cause the background to be cleared and redraw.
        count = 6
        DrawToBuffer(grafx.Graphics)
        Me.Refresh()
    End Sub    
    
    Private Sub DrawToBuffer(g As Graphics)
        ' Clear the graphics buffer every five updates.
        count = count+1
        If count > 5 Then
            count = 0
            grafx.Graphics.FillRectangle(Brushes.Black, 0, 0, Me.Width, Me.Height)
        End If
        
        ' Draw randomly positioned and colored ellipses.
        Dim rnd As New Random()
        Dim i As Integer
        For i = 0 To 21
            Dim px As Integer = rnd.Next(20, Me.Width - 40)
            Dim py As Integer = rnd.Next(20, Me.Height - 40)
            g.DrawEllipse(New Pen(Color.FromArgb(rnd.Next(0, 255), rnd.Next(0, 255), _
                rnd.Next(0, 255)), 1), px, py, px + rnd.Next(0, Me.Width - px - 20), _
                py + rnd.Next(0, Me.Height - py - 20))
        Next i
        
        ' Draw information strings.
        g.DrawString("Buffering Mode: " + bufferingModeStrings(bufferingMode), _
            New Font("Arial", 8), Brushes.White, 10, 10)
        g.DrawString("Right-click to cycle buffering mode", New Font("Arial", 8), _
            Brushes.White, 10, 22)
        g.DrawString("Left-click to toggle timed display refresh", _
            New Font("Arial", 8), Brushes.White, 10, 34)
    End Sub    
    
    Protected Overrides Sub OnPaint(e As PaintEventArgs)
        grafx.Render(e.Graphics)
    End Sub   
    
    <STAThread()>  _
    Public Shared Sub Main(args() As String)
        Application.Run(New BufferingExample())
    End Sub

End Class


package BufferingExample; 

import System.*;
import System.ComponentModel.*;
import System.Drawing.*;
import System.Windows.Forms.*;

public class BufferingExample extends Form
{
    private BufferedGraphicsContext context;
    private BufferedGraphics grafx;
    private ubyte bufferingMode;
    private String bufferingModeStrings[] =  
        { "Draw to Form without OptimizedDoubleBufferring control style", 
        "Draw to Form using OptimizedDoubleBuffering control style", 
        "Draw to HDC for form" };
    private System.Windows.Forms.Timer timer1;
    private ubyte count;

    public BufferingExample()
    {
        super();
        // Configure the Form for this example.
        this.set_Text("User double buffering");
        this.add_MouseDown(new MouseEventHandler(this.MouseDownHandler));
        this.add_Resize(new EventHandler(this.OnResize));
        this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);
        // Configure a timer to draw graphics updates.
        timer1 = new System.Windows.Forms.Timer();
        timer1.set_Interval(200);
        timer1.add_Tick(new EventHandler(this.OnTimer));
        bufferingMode = 2;
        count = 0;
        // Retrieves the BufferedGraphicsContext for the 
        // current application domain.
        context = BufferedGraphicsManager.get_Current();
        // 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.set_MaximumBuffer(new Size(this.get_Width() + 1, this.get_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.get_Width(), this.get_Height()));
        // Draw the first frame to the buffer.
        DrawToBuffer(grafx.get_Graphics());
    } //BufferingExample

    private void MouseDownHandler(Object sender, MouseEventArgs e)
    {
        if (e.get_Button().Equals(MouseButtons.Right)) {
            // Cycle the buffering mode.
            if (++bufferingMode > 2) {
                bufferingMode = 0;
            }

            // If the previous buffering mode used 
            // the OptimizedDoubleBuffering ControlStyle,
            // disable the control style.
            if (bufferingMode == 1) {
                this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            }

            // If the current buffering mode uses
            // the OptimizedDoubleBuffering ControlStyle,
            // enabke the control style.
            if (bufferingMode == 2) {
                this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
            }

            // Cause the background to be cleared and redraw.
            count = 6;
            DrawToBuffer(grafx.get_Graphics());
            this.Refresh();
        }
        else {
            // Toggle whether the redraw timer is active.
            if (timer1.get_Enabled()) {
                timer1.Stop();
            }
            else {
                timer1.Start();
            }
        }
    } //MouseDownHandler

    private void OnTimer(Object sender, EventArgs e)
    {
        // Draw randomly positioned ellipses to the buffer.
        DrawToBuffer(grafx.get_Graphics());

        // If in bufferingMode 2, draw to the form's HDC.
        if (bufferingMode == 2) {
            // Render the graphics buffer to the form's HDC.
            grafx.Render(this.get_Handle());
        }
        // If in bufferingMode 0 or 1, draw in the paint method.
        else {
            this.Refresh();
        }
    } //OnTimer

    private void OnResize(Object sender, EventArgs e)
    {
        // Re-create the graphics buffer for a new window size.
        context.set_MaximumBuffer(new Size(this.get_Width() + 1, 
            this.get_Height() + 1));
        if (grafx != null) {
            grafx.Dispose();
            grafx = null;
        }
        grafx = context.Allocate(this.CreateGraphics(), 
            new Rectangle(0, 0, this.get_Width(), this.get_Height()));

        // Cause the background to be cleared and redraw.
        count = 6;
        DrawToBuffer(grafx.get_Graphics());
        this.Refresh();
    } //OnResize

    private void DrawToBuffer(Graphics g)
    {
        // Clear the graphics buffer every five updates.
        if (++count > 5) {
            count = 0;
            grafx.get_Graphics().FillRectangle(Brushes.get_Black(), 0, 0, 
                this.get_Width(), this.get_Height());
        }

        // Draw randomly positioned and colored ellipses.
        Random rnd = new Random();
        for (int i = 0; i < 20; i++) {
            int px = rnd.Next(20, this.get_Width() - 40);
            int py = rnd.Next(20, this.get_Height() - 40);
            g.DrawEllipse(new Pen(Color.FromArgb(rnd.Next(0, 255), 
                rnd.Next(0, 255), rnd.Next(0, 255)), 1), px, py, 
                px + rnd.Next(0, this.get_Width() - px - 20), 
                py + rnd.Next(0, this.get_Height() - py - 20));
        }

        // Draw information strings.
        g.DrawString("Buffering Mode: " 
            + bufferingModeStrings.get_Item(bufferingMode), 
            new Font("Arial", 8), Brushes.get_White(), 10, 10);
        g.DrawString("Right-click to cycle buffering mode", 
            new Font("Arial", 8), Brushes.get_White(), 10, 22);
        g.DrawString("Left-click to toggle timed display refresh",
            new Font("Arial", 8), Brushes.get_White(), 10, 34);
    } //DrawToBuffer

    protected void OnPaint(PaintEventArgs e)
    {
        grafx.Render(e.get_Graphics());
    } //OnPaint

    /** @attribute STAThread()
     */
    public static void main(String[] args)
    {
        Application.Run(new BufferingExample());
    } //main
} //BufferingExample

System.Object
  System.Drawing.BufferedGraphics

The BufferedGraphics class is not thread safe. When accessing a graphics buffer from separate threads, it is important to use a thread-access control mechanism to prevent conflicts.

Windows 98, Windows Server 2000 SP4, Windows Millennium Edition, Windows Server 2003, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP SP2, Windows XP Starter Edition

The Microsoft .NET Framework 3.0 is supported on Windows Vista, Microsoft Windows XP SP2, and Windows Server 2003 SP1.

.NET Framework

Supported in: 3.0, 2.0

Community Additions

ADD
Show:
© 2014 Microsoft