BufferedGraphics 類別

定義

提供雙重緩衝的圖形緩衝區。

public ref class BufferedGraphics sealed : IDisposable
public sealed class BufferedGraphics : IDisposable
type BufferedGraphics = class
    interface IDisposable
Public NotInheritable Class BufferedGraphics
Implements IDisposable
繼承
BufferedGraphics
實作

範例

下列程式代碼範例示範如何使用 BufferedGraphics 物件,使用數種類型的緩衝實作來繪製圖形。 按兩下窗體會以替代方式啟動,並停止導致繪製更新的定時器。 繪製更新可讓您觀察雙緩衝的效果。 以滑鼠右鍵按單擊窗體會循環執行下列繪圖模式:

在每個模式中,會繪製識別目前模式的文字,並描述按下每個滑鼠按鈕時所發生的行為。

#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

備註

類別 BufferedGraphics 可讓您實作圖形的自定義雙精度浮點數緩衝。 它提供圖形緩衝區的包裝函式,以及可用來寫入緩衝區的方法,並將其內容轉譯至輸出裝置。

使用雙緩衝的圖形可以減少或消除重繪顯示介面所造成的閃爍。 當您使用雙緩衝處理時,更新的圖形會先繪製到記憶體中的緩衝區,然後這個緩衝區的內容會快速寫入部分或所有顯示的介面。 這個相對簡短的顯示圖形覆寫通常會減少或消除在更新圖形時有時會發生的閃爍。

注意

在 .NET 6 和更新版本中,只有 Windows 作業系統才支援包含此類型的 System.Drawing.Common 套件。 在跨平臺應用程式中使用此類型會導致編譯時期警告和運行時間例外狀況。 如需詳細資訊,請參閱 僅限 Windows 上支援的 System.Drawing.Common

注意

使用雙緩衝的最簡單方式是使用 SetStyle 方法,OptimizedDoubleBuffer在控件上設定控件樣式旗標。 OptimizedDoubleBuffer設定 控件的旗標會透過預設圖形緩衝區重新導向控件的所有繪製,而不需要任何其他程序代碼。 此旗標預設會設定為 true

類別BufferedGraphics沒有公用建構函式,而且必須使用其 Allocate 方法,BufferedGraphicsContext為應用程式域建立 。 您可以從靜態BufferedGraphicsManager.Current屬性擷取BufferedGraphicsContext應用程式域的 。

屬性 Graphics 可用於繪製圖形緩衝區。 這個屬性可讓您存取 Graphics 繪製至配置給這個 BufferedGraphics 物件的圖形緩衝區的物件。

Render沒有自變數的方法會將圖形緩衝區的內容繪製到配置緩衝區時所指定的介面。 方法的其他多載 Render 可讓您指定 Graphics 指向要繪製圖形緩衝區內容的裝置內容的物件或 IntPtr 物件。

如需繪製雙緩衝圖形的詳細資訊,請參閱 雙緩衝圖形

屬性

Graphics

取得 Graphics 物件,該物件輸出至圖形緩衝區。

方法

Dispose()

釋放由 BufferedGraphics 物件使用的所有資源。

Equals(Object)

判斷指定的物件是否等於目前的物件。

(繼承來源 Object)
Finalize()

允許物件在記憶體回收進行回收之前,嘗試釋放資源並執行其他清除作業。

GetHashCode()

做為預設雜湊函式。

(繼承來源 Object)
GetType()

取得目前執行個體的 Type

(繼承來源 Object)
MemberwiseClone()

建立目前 Object 的淺層複製。

(繼承來源 Object)
Render()

將圖形緩衝區的內容寫入預設裝置。

Render(Graphics)

將圖形緩衝區的內容寫入指定的 Graphics 物件。

Render(IntPtr)

將圖形緩衝區的內容寫入與指定 IntPtr 控制代碼關聯的裝置內容。

ToString()

傳回代表目前物件的字串。

(繼承來源 Object)

適用於

執行緒安全性

BufferedGraphics 類別不具備執行緒安全。 從不同的線程存取圖形緩衝區時,請務必使用線程訪問控制機制來防止衝突。

另請參閱