BufferedGraphics Classe
Definição
Importante
Algumas informações se referem a produtos de pré-lançamento que podem ser substancialmente modificados antes do lançamento. A Microsoft não oferece garantias, expressas ou implícitas, das informações aqui fornecidas.
Fornece um buffer de gráficos para buffer duplo.
public ref class BufferedGraphics sealed : IDisposable
public sealed class BufferedGraphics : IDisposable
type BufferedGraphics = class
interface IDisposable
Public NotInheritable Class BufferedGraphics
Implements IDisposable
- Herança
-
BufferedGraphics
- Implementações
Exemplos
O exemplo de código a seguir demonstra o uso de um BufferedGraphics objeto para desenhar gráficos usando vários tipos de implementações de buffer. Clicar no formulário alternadamente inicia e interrompe um temporizador que causa atualizações de desenho. As atualizações de desenho permitem observar o efeito do buffer duplo. Clicar com o botão direito do mouse no formulário percorre os seguintes modos de desenho:
Desenho substituindo o OnPaint método usando o OptimizedDoubleBuffer estilo de controle.
Desenho substituindo o OnPaint método para o método de formulário sem usar o OptimizedDoubleBuffer estilo de controle.
Em cada modo, o texto é desenhado que identifica o modo atual e descreve o comportamento que ocorre quando cada botão do mouse é pressionado.
#using <System.Windows.Forms.dll>
#using <System.Drawing.dll>
#using <System.dll>
using namespace System;
using namespace System::ComponentModel;
using namespace System::Drawing;
using namespace System::Windows::Forms;
namespace BufferingExample
{
public ref class BufferingExample: public Form
{
private:
BufferedGraphicsContext^ context;
BufferedGraphics^ grafx;
Byte bufferingMode;
array<String^>^bufferingModeStrings;
System::Windows::Forms::Timer^ timer1;
Byte count;
public:
BufferingExample()
: Form()
{
array<String^>^tempStrings = {"Draw to Form without OptimizedDoubleBufferring control style","Draw to Form using OptimizedDoubleBuffering control style","Draw to HDC for form"};
bufferingModeStrings = tempStrings;
// Configure the Form for this example.
this->Text = "User double buffering";
this->MouseDown += gcnew MouseEventHandler( this, &BufferingExample::MouseDownHandler );
this->Resize += gcnew EventHandler( this, &BufferingExample::OnResize );
this->SetStyle( static_cast<ControlStyles>(ControlStyles::AllPaintingInWmPaint | ControlStyles::UserPaint), true );
// Configure a timer to draw graphics updates.
timer1 = gcnew System::Windows::Forms::Timer;
timer1->Interval = 200;
timer1->Tick += gcnew EventHandler( this, &BufferingExample::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 = System::Drawing::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(), Rectangle(0,0,this->Width,this->Height) );
// Draw the first frame to the buffer.
DrawToBuffer( grafx->Graphics );
}
private:
void MouseDownHandler( Object^ /*sender*/, MouseEventArgs^ e )
{
if ( e->Button == ::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->Graphics );
this->Refresh();
}
else
{
// Toggle whether the redraw timer is active.
if ( timer1->Enabled )
timer1->Stop();
else
timer1->Start();
}
}
private:
void OnTimer( Object^ /*sender*/, EventArgs^ /*e*/ )
{
// Draw randomly positioned ellipses to the buffer.
DrawToBuffer( grafx->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( Graphics::FromHwnd( this->Handle ) );
// If in bufferingMode 0 or 1, draw in the paint method.
else
// If in bufferingMode 0 or 1, draw in the paint method.
this->Refresh();
}
void OnResize( Object^ /*sender*/, EventArgs^ /*e*/ )
{
// Re-create the graphics buffer for a new window size.
context->MaximumBuffer = System::Drawing::Size( this->Width + 1, this->Height + 1 );
if ( grafx != nullptr )
{
delete grafx;
grafx = nullptr;
}
grafx = context->Allocate( this->CreateGraphics(), Rectangle(0,0,this->Width,this->Height) );
// Cause the background to be cleared and redraw.
count = 6;
DrawToBuffer( grafx->Graphics );
this->Refresh();
}
void DrawToBuffer( Graphics^ g )
{
// Clear the graphics buffer every five updates.
if ( ++count > 5 )
{
count = 0;
grafx->Graphics->FillRectangle( Brushes::Black, 0, 0, this->Width, this->Height );
}
// Draw randomly positioned and colored ellipses.
Random^ rnd = gcnew Random;
for ( int i = 0; i < 20; i++ )
{
int px = rnd->Next( 20, this->Width - 40 );
int py = rnd->Next( 20, this->Height - 40 );
g->DrawEllipse( gcnew Pen( Color::FromArgb( rnd->Next( 0, 255 ), rnd->Next( 0, 255 ), rnd->Next( 0, 255 ) ), 1.0f ), px, py, px + rnd->Next( 0, this->Width - px - 20 ), py + rnd->Next( 0, this->Height - py - 20 ) );
}
// Draw information strings.
g->DrawString( String::Format( "Buffering Mode: {0}", bufferingModeStrings[ bufferingMode ] ), gcnew System::Drawing::Font( "Arial",8 ), Brushes::White, 10, 10 );
g->DrawString( "Right-click to cycle buffering mode", gcnew System::Drawing::Font( "Arial",8 ), Brushes::White, 10, 22 );
g->DrawString( "Left-click to toggle timed display refresh", gcnew System::Drawing::Font( "Arial",8 ), Brushes::White, 10, 34 );
}
protected:
virtual void OnPaint( PaintEventArgs^ e ) override
{
grafx->Render( e->Graphics );
}
};
}
[STAThread]
int main()
{
Application::Run( gcnew BufferingExample::BufferingExample );
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace BufferingExample
{
public class BufferingExample : Form
{
private BufferedGraphicsContext context;
private BufferedGraphics grafx;
private byte 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 byte count;
public BufferingExample() : base()
{
// Configure the Form for this example.
this.Text = "User double buffering";
this.MouseDown += new MouseEventHandler(this.MouseDownHandler);
this.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.Interval = 200;
timer1.Tick += new EventHandler(this.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(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);
}
private void MouseDownHandler(object sender, MouseEventArgs e)
{
if( e.Button == 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.Graphics);
this.Refresh();
}
else
{
// Toggle whether the redraw timer is active.
if( timer1.Enabled )
timer1.Stop();
else
timer1.Start();
}
}
private void OnTimer(object sender, EventArgs e)
{
// Draw randomly positioned ellipses to the buffer.
DrawToBuffer(grafx.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(Graphics.FromHwnd(this.Handle));
// If in bufferingMode 0 or 1, draw in the paint method.
else
this.Refresh();
}
private void OnResize(object sender, EventArgs e)
{
// Re-create the graphics buffer for a new window size.
context.MaximumBuffer = new Size(this.Width+1, this.Height+1);
if( grafx != null )
{
grafx.Dispose();
grafx = null;
}
grafx = context.Allocate(this.CreateGraphics(),
new Rectangle( 0, 0, this.Width, this.Height ));
// Cause the background to be cleared and redraw.
count = 6;
DrawToBuffer(grafx.Graphics);
this.Refresh();
}
private void DrawToBuffer(Graphics g)
{
// Clear the graphics buffer every five updates.
if( ++count > 5 )
{
count = 0;
grafx.Graphics.FillRectangle(Brushes.Black, 0, 0, this.Width, this.Height);
}
// Draw randomly positioned and colored ellipses.
Random rnd = new Random();
for( int i=0; i<20; i++ )
{
int px = rnd.Next(20,this.Width-40);
int py = rnd.Next(20,this.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.Width-px-20), py+rnd.Next(0, this.Height-py-20));
}
// 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);
}
protected override void OnPaint(PaintEventArgs e)
{
grafx.Render(e.Graphics);
}
[STAThread]
public static void Main(string[] args)
{
Application.Run(new BufferingExample());
}
}
}
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
Comentários
A BufferedGraphics classe permite que você implemente buffer duplo personalizado para seus gráficos. Ele fornece um wrapper para um buffer gráfico, juntamente com métodos que você pode usar para gravar no buffer e renderizar seu conteúdo em um dispositivo de saída.
Os gráficos que usam buffer duplo podem reduzir ou eliminar a cintilação causada pelo redesenho de uma superfície de exibição. Quando você usa buffer duplo, os gráficos atualizados são desenhados primeiro para um buffer na memória e o conteúdo desse buffer é gravado rapidamente em alguns ou em toda a superfície exibida. Essa substituição relativamente breve dos gráficos exibidos normalmente reduz ou elimina a cintilação que, às vezes, ocorre quando os gráficos são atualizados.
Observação
No .NET 6 e versões posteriores, o pacote System.Drawing.Common, que inclui esse tipo, só tem suporte em sistemas operacionais Windows. O uso desse tipo em aplicativos multiplataforma causa avisos de tempo de compilação e exceções em tempo de execução. Para obter mais informações, consulte System.Drawing.Common com suporte apenas no Windows.
Observação
A maneira mais simples de usar buffer duplo é definir o OptimizedDoubleBuffer sinalizador de estilo de controle em um controle usando o SetStyle método . Definir o OptimizedDoubleBuffer sinalizador para um controle redireciona toda a pintura para o controle por meio de um buffer gráfico padrão, sem exigir nenhum código adicional. Esse sinalizador é definido true
como por padrão.
A BufferedGraphics classe não tem construtor público e deve ser criada pelo BufferedGraphicsContext para um domínio de aplicativo usando seu Allocate método. Você pode recuperar o BufferedGraphicsContext para o domínio do aplicativo atual da propriedade estática BufferedGraphicsManager.Current .
A Graphics propriedade pode ser usada para desenhar no buffer de gráficos. Essa propriedade fornece acesso ao Graphics objeto que desenha para o buffer de gráficos alocado para esse BufferedGraphics objeto.
O Render método sem argumentos desenha o conteúdo do buffer gráfico para a superfície especificada quando o buffer foi alocado. Outras sobrecargas do Render método permitem que você especifique um Graphics objeto ou um IntPtr objeto que aponte para um contexto de dispositivo para o qual desenhar o conteúdo do buffer gráfico.
Para obter mais informações sobre como desenhar gráficos com buffer duplo, consulte Elementos gráficos em buffer duplo.
Propriedades
Graphics |
Obtém um objeto Graphics que gera saídas para o buffer de gráficos. |
Métodos
Dispose() |
Libera todos os recursos usados pelo objeto BufferedGraphics. |
Equals(Object) |
Determina se o objeto especificado é igual ao objeto atual. (Herdado de Object) |
Finalize() |
Permite que um objeto tente liberar recursos e executar outras operações de limpeza antes de ser recuperado pela coleta de lixo. |
GetHashCode() |
Serve como a função de hash padrão. (Herdado de Object) |
GetType() |
Obtém o Type da instância atual. (Herdado de Object) |
MemberwiseClone() |
Cria uma cópia superficial do Object atual. (Herdado de Object) |
Render() |
Grava o conteúdo do buffer de gráficos no dispositivo padrão. |
Render(Graphics) |
Grava o conteúdo do buffer gráfico no objeto Graphics especificado. |
Render(IntPtr) |
Grava o conteúdo do buffer de gráficos no contexto de dispositivo associado ao identificador IntPtr especificado. |
ToString() |
Retorna uma cadeia de caracteres que representa o objeto atual. (Herdado de Object) |
Aplica-se a
Acesso thread-safe
A classe BufferedGraphics não é segura para threads. Ao acessar um buffer de gráficos de threads separados, é importante usar um mecanismo de controle de acesso a threads para evitar conflitos.