大家好,今天介绍BufferedGraphics 类,它的定义为双缓冲提供图形缓冲区。
下面是其示例:
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 对象,该对象指向要绘制图形缓冲区内容的设备上下文。
有关绘制双缓冲图形的详细信息,请参阅 双缓冲图形。
需要注意的地方:
BufferedGraphics.Dispose 方法:释放由 BufferedGraphics 对象使用的所有资源。
注释:
使用 完 对象后调用 DisposeBufferedGraphics 。 方法 Dispose 使 BufferedGraphics 对象处于不可用状态。 调用 Dispose后,必须释放对 BufferedGraphics 对象的所有引用,以便垃圾回收器可以回收对象占用的 BufferedGraphics 内存。