BufferedGraphics Klasa
Definicja
Ważne
Niektóre informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany przed wydaniem. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.
Zapewnia bufor graficzny do podwójnego buforowania.
public ref class BufferedGraphics sealed : IDisposable
public sealed class BufferedGraphics : IDisposable
type BufferedGraphics = class
interface IDisposable
Public NotInheritable Class BufferedGraphics
Implements IDisposable
- Dziedziczenie
-
BufferedGraphics
- Implementuje
Przykłady
Poniższy przykład kodu przedstawia użycie BufferedGraphics obiektu do rysowania grafiki przy użyciu kilku typów implementacji buforowania. Kliknięcie formularza jest na przemian uruchamiane i zatrzymuje czasomierz, który powoduje narysowanie aktualizacji. Aktualizacje rysowania umożliwiają obserwowanie wpływu podwójnego buforowania. Kliknięcie prawym przyciskiem myszy formularza przechodzi przez następujące tryby rysunku:
Rysowanie przez zastąpienie OnPaint metody przy użyciu stylu kontrolki OptimizedDoubleBuffer .
Rysowanie przez zastąpienie OnPaint metody formularza bez użycia stylu kontrolki OptimizedDoubleBuffer .
W każdym trybie tekst jest rysowany, który identyfikuje bieżący tryb i opisuje zachowanie występujące po naciśnięciu każdego przycisku myszy.
#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
Uwagi
Klasa BufferedGraphics umożliwia zaimplementowanie niestandardowego podwójnego buforowania dla grafiki. Zapewnia otokę buforu graficznego wraz z metodami, których można użyć do zapisywania w buforze i renderowania jego zawartości na urządzeniu wyjściowym.
Grafika używająca podwójnego buforowania może zmniejszyć lub wyeliminować migotanie spowodowane ponownym rysowaniem powierzchni ekranu. W przypadku używania podwójnego buforowania zaktualizowana grafika jest najpierw rysowana do buforu w pamięci, a zawartość tego buforu jest następnie szybko zapisywana na niektórych lub wszystkich wyświetlanych powierzchniach. To stosunkowo krótkie zastąpienie wyświetlanej grafiki zwykle zmniejsza lub eliminuje migotanie, które czasami występuje podczas aktualizacji grafiki.
Uwaga
W programie .NET 6 i nowszych wersjach pakiet System.Drawing.Common,który zawiera ten typ, jest obsługiwany tylko w Windows operacyjnych. Użycie tego typu w aplikacjach międzyplatformowych powoduje ostrzeżenia w czasie kompilacji i wyjątki czasu uruchamiania. Aby uzyskać więcej informacji, zobacz System.Drawing.Common obsługiwane tylko na Windows.
Uwaga
Najprostszym sposobem użycia podwójnego buforowania jest ustawienie OptimizedDoubleBuffer flagi stylu kontrolki w kontrolce przy użyciu SetStyle metody . OptimizedDoubleBuffer Ustawienie flagi dla kontrolki przekierowuje wszystkie obrazy kontrolki za pomocą domyślnego buforu graficznego bez konieczności dodatkowego kodu. Ta flaga jest domyślnie ustawiona na true .
Klasa BufferedGraphics nie ma publicznego konstruktora i musi zostać utworzona przez BufferedGraphicsContext klasę dla domeny aplikacji przy użyciu jej Allocate metody. Element dla bieżącej domeny aplikacji można pobrać BufferedGraphicsContext z właściwości statycznej BufferedGraphicsManager.Current .
Właściwość Graphics może służyć do rysowania do buforu graficznego. Ta właściwość zapewnia dostęp do Graphics obiektu, który pobiera do buforu graficznego przydzielonego dla tego BufferedGraphics obiektu.
Metoda Render bez argumentów pobiera zawartość buforu graficznego na powierzchnię określoną podczas przydzielania buforu. Inne przeciążenia Render metody umożliwiają określenie Graphics obiektu lub IntPtr obiektu wskazującego kontekst urządzenia, do którego ma być pobierana zawartość buforu graficznego.
Aby uzyskać więcej informacji na temat rysunku grafiki z podwójnym buforem, zobacz Podwójna grafika buforowana.
Właściwości
| Graphics |
Graphics Pobiera obiekt, który zwraca dane wyjściowe do buforu graficznego. |
Metody
| Dispose() |
Zwalnia wszystkie zasoby używane przez BufferedGraphics obiekt . |
| Equals(Object) |
Określa, czy dany obiekt jest taki sam, jak bieżący obiekt. (Odziedziczone po Object) |
| Finalize() |
Umożliwia obiektowi próbę zwolnienia zasobów i wykonania innych operacji oczyszczania przed odzyskaniem przez odzyskiwanie pamięci. |
| GetHashCode() |
Służy jako domyślna funkcja skrótu. (Odziedziczone po Object) |
| GetType() |
Type Pobiera wartość bieżącego wystąpienia. (Odziedziczone po Object) |
| MemberwiseClone() |
Tworzy płytkią kopię bieżącego Objectelementu . (Odziedziczone po Object) |
| Render() |
Zapisuje zawartość buforu graficznego na urządzeniu domyślnym. |
| Render(Graphics) |
Zapisuje zawartość buforu graficznego do określonego Graphics obiektu. |
| Render(IntPtr) |
Zapisuje zawartość buforu graficznego w kontekście urządzenia skojarzonym z określonym IntPtr dojściem. |
| ToString() |
Zwraca ciąg reprezentujący bieżący obiekt. (Odziedziczone po Object) |
Dotyczy
Bezpieczeństwo wątkowe
Klasa BufferedGraphics nie jest bezpieczna wątkiem. Podczas uzyskiwania dostępu do buforu graficznego z oddzielnych wątków należy użyć mechanizmu kontroli dostępu wątków, aby zapobiec konfliktom.