BufferedGraphics Klass
Definition
Viktigt
En del information gäller för förhandsversionen av en produkt och kan komma att ändras avsevärt innan produkten blir allmänt tillgänglig. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, avseende informationen som visas här.
Tillhandahåller en grafikbuffert för dubbel buffring.
public ref class BufferedGraphics sealed : IDisposable
public sealed class BufferedGraphics : IDisposable
type BufferedGraphics = class
interface IDisposable
Public NotInheritable Class BufferedGraphics
Implements IDisposable
- Arv
-
BufferedGraphics
- Implementeringar
Exempel
Följande kodexempel visar hur du använder ett BufferedGraphics objekt för att rita grafik med hjälp av flera typer av buffringsimplementeringar. Om du klickar på formuläret startas och stoppas en timer som orsakar dragningsuppdateringar. Med dragningsuppdateringarna kan du observera effekten av dubbel buffring. När du högerklickar på formuläret växlar du genom följande ritningslägen:
Rita genom att OnPaint åsidosätta metoden med hjälp av kontrollformatet OptimizedDoubleBuffer .
Rita genom att OnPaint åsidosätta metoden för formulärmetoden utan att använda kontrollformatet OptimizedDoubleBuffer .
I varje läge ritas text som identifierar det aktuella läget och beskriver det beteende som inträffar när varje musknapp trycks in.
#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
Kommentarer
Med BufferedGraphics klassen kan du implementera anpassad dubbel buffring för din grafik. Den tillhandahåller en omslutning för en grafikbuffert, tillsammans med metoder som du kan använda för att skriva till bufferten och återge dess innehåll till en utdataenhet.
Grafik som använder dubbel buffring kan minska eller eliminera flimmer som orsakas av att en visningsyta ritas om. När du använder dubbel buffring ritas uppdaterade grafik först till en buffert i minnet, och innehållet i den här bufferten skrivs sedan snabbt till en del av eller hela den visade ytan. Den här relativt korta överskrivningen av den visade grafiken minskar eller eliminerar vanligtvis det flimmer som ibland uppstår när grafiken uppdateras.
Note
I .NET 6 och senare versioner stöds endast System.Drawing.Common-paketet, som innehåller den här typen, på Windows-operativsystem. Användning av den här typen i plattformsoberoende appar orsakar kompileringstidsvarningar och körningsfel. Mer information finns i System.Drawing.Common som endast stöds i Windows.
Note
Det enklaste sättet att använda dubbel buffring är att ange OptimizedDoubleBuffer kontrollformatflaggan för en kontroll med hjälp av SetStyle metoden.
OptimizedDoubleBuffer Om du anger flaggan för en kontroll omdirigeras all målning för kontrollen via en standardgrafikbuffert, utan att det krävs någon ytterligare kod. Den här flaggan är inställd true på som standard.
Klassen BufferedGraphics har ingen offentlig konstruktor och måste skapas av för en programdomän med hjälp av BufferedGraphicsContext dess Allocate metod. Du kan hämta BufferedGraphicsContext för den aktuella programdomänen från den statiska BufferedGraphicsManager.Current egenskapen.
Egenskapen Graphics kan användas för att rita till grafikbufferten. Den här egenskapen ger åtkomst till objektet Graphics som ritar till grafikbufferten som allokerats för det här BufferedGraphics objektet.
Metoden Render utan argument ritar innehållet i grafikbufferten till den yta som angavs när bufferten allokerades. Med andra överlagringar av Render metoden kan du ange ett Graphics objekt eller ett IntPtr objekt som pekar på en enhetskontext som du kan rita innehållet i grafikbufferten till.
Mer information om hur du ritar dubbelbuffertad grafik finns i Dubbelbuffrad grafik.
Egenskaper
| Name | Description |
|---|---|
| Graphics |
Hämtar ett Graphics objekt som matar ut till grafikbufferten. |
Metoder
| Name | Description |
|---|---|
| Dispose() |
Frigör alla resurser som används av BufferedGraphics objektet. |
| Equals(Object) |
Avgör om det angivna objektet är lika med det aktuella objektet. (Ärvd från Object) |
| Finalize() |
Tillåter att ett objekt försöker frigöra resurser och utföra andra rensningsåtgärder innan det frigörs av skräpinsamling. |
| GetHashCode() |
Fungerar som standard-hash-funktion. (Ärvd från Object) |
| GetType() |
Hämtar den aktuella instansen Type . (Ärvd från Object) |
| MemberwiseClone() |
Skapar en ytlig kopia av den aktuella Object. (Ärvd från Object) |
| Render() |
Skriver innehållet i grafikbufferten till standardenheten. |
| Render(Graphics) |
Skriver innehållet i grafikbufferten till det angivna Graphics objektet. |
| Render(IntPtr) |
Skriver innehållet i grafikbufferten till enhetskontexten som är associerad med det angivna IntPtr handtaget. |
| ToString() |
Returnerar en sträng som representerar det aktuella objektet. (Ärvd från Object) |
Gäller för
Trådsäkerhet
Klassen BufferedGraphics är inte trådsäker. När du kommer åt en grafikbuffert från separata trådar är det viktigt att använda en mekanism för trådåtkomstkontroll för att förhindra konflikter.