BufferedGraphics 类

定义

为双缓冲提供图形缓冲区。

C#
public sealed class BufferedGraphics : IDisposable
继承
BufferedGraphics
实现

示例

下面的代码示例演示如何使用 BufferedGraphics 对象通过多种类型的缓冲实现来绘制图形。 单击窗体交替启动并停止导致绘图更新的计时器。 绘制更新使你能够观察双重缓冲的效果。 右键单击窗体可循环浏览以下绘制模式:

在每个模式下,都会绘制标识当前模式的文本,并描述按下每个鼠标按钮时发生的行为。

C#
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());
        }
    }
}

注解

BufferedGraphics 允许你为图形实现自定义双重缓冲。 它为图形缓冲区提供包装器,以及可用于写入缓冲区并将其内容呈现到输出设备的方法。

使用双重缓冲的图形可以减少或消除重绘显示图面导致的闪烁。 使用双重缓冲时,将首先将更新的图形绘制到内存中的缓冲区,然后将此缓冲区的内容快速写入部分或全部显示的图面。 对显示的图形的这种相对简短的覆盖通常会减少或消除更新图形时有时发生的闪烁。

备注

在 .NET 6 及更高版本中, System.Drawing.Common 包(包括此类型)仅在 Windows 操作系统上受支持。 在跨平台应用中使用此类型会导致编译时警告和运行时异常。 有关详细信息,请参阅 仅在 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)

适用于

产品 版本
.NET Framework 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
Windows Desktop 3.0, 3.1, 5, 6, 7, 8, 9

线程安全性

BufferedGraphics 类不是线程安全的。 从单独的线程访问图形缓冲区时,请务必使用线程访问控制机制来防止冲突。

另请参阅