[英]Double buffering on .NET Compact Framework
我想知道是否有人可以向我解释如何在.net紧凑框架中双缓冲完整表单。 我已经找到了双缓冲的例子,但是我似乎无法使它们工作。
我们创建了具有多种形式的应用程序。 其中一些表格确实需要很长时间才能在屏幕上绘制,从而导致闪烁。 为了让您对我们的应用程序有一些了解,我将解释其中一种形式。 该表单包含一个usercontrol,一些面板,文本框和按钮。 用户控件的面板具有自定义绘图(在屏幕上绘制文本和图像(具有透明性))。 甚至这些面板中的某些面板都包含其他做相同事情的面板。 这些面板也具有自定义绘制,因为我们在屏幕上绘制带有某些效果等的文本。每个面板都需要花费一定的绘制时间,这意味着如果我们在3x3网格中有9个面板,它们将被绘制并以随机顺序显示,而不是发出蜂鸣声同时显示所有内容。 文本绘图等也一样。我们希望同时显示表单上的所有内容。
所以我的问题是,我可以创建一个执行双缓冲的“超级”类吗,图形是否存储在完整表格中?
我可以从中扩展当前的表格,而无需更改控件,面板,图像的绘制等吗?
谢谢
我不确定所有控件上的确切形式的复杂性,但是我已经实现了基本的DoubleBufferableControl
类,您可以从中扩展该类以创建具有双缓冲的自定义控件。 我用自定义图形创建了许多控件,这些控件均以此为基类。
您可以使用此类作为控件的基类,这些控件具有自定义绘画功能,以防止闪烁。 在子类中,请确保在构造函数中将DoubleBuffered设置为true。
/// <summary>
/// Implements the functionality for a control that can be double buffered
/// </summary>
public class DoubleBufferableControl : ScrollableControl
{
public event BufferedPaintEventHandler BufferedPaint;
private bool doubleBuffered;
private Bitmap backBuffer;
private Size oldSize;
/// <summary>
/// Gets or sets whether this control will use double buffering
/// </summary>
public bool DoubleBuffered
{
get
{
return doubleBuffered;
}
set
{
if (value && !doubleBuffered && Width > 0 && Height > 0)
{
backBuffer = new Bitmap(Width, Height);
}
else if(!value && doubleBuffered)
{
backBuffer.Dispose();
backBuffer = null;
}
doubleBuffered = value;
}
}
/// <summary>
/// Gets the off screen image used for double buffering
/// </summary>
public Bitmap BackBuffer
{
get
{
return backBuffer;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="DoubleBufferableControl"/> class.
/// </summary>
public DoubleBufferableControl()
{
AutoScroll = false;
doubleBuffered = DefaultDoubleBuffered;
oldSize = Size;
}
#region Designer
private bool DefaultDoubleBuffered = false;
protected virtual bool ShouldSerializeDoubleBuffered()
{
return !this.doubleBuffered.Equals(DefaultDoubleBuffered);
}
protected void ResetDoubleBuffered()
{
DoubleBuffered = DefaultDoubleBuffered;
}
#endregion
/// <summary>
/// Raises the Paint event
/// </summary>
/// <param name="e">A PaintEventArgs that represents event data</param>
protected override sealed void OnPaint(PaintEventArgs e)
{
if (doubleBuffered)
{
DoubleBufferedPaintEventArgs pe = new DoubleBufferedPaintEventArgs(CreateGraphics(), e.ClipRectangle);
OnPaint(pe);
pe.Graphics.Dispose();
e.Graphics.DrawImage(backBuffer, e.ClipRectangle, e.ClipRectangle, GraphicsUnit.Pixel);
base.OnPaint(e);
}
else
{
DoubleBufferedPaintEventArgs pe = new DoubleBufferedPaintEventArgs(e.Graphics, e.ClipRectangle);
OnPaint(pe);
base.OnPaint(e);
}
}
/// <summary>
/// Raises the Paint event for child classes that are to be double buffered
/// </summary>
/// <param name="e"></param>
protected virtual void OnPaint(DoubleBufferedPaintEventArgs e)
{
if (BufferedPaint != null)
BufferedPaint(this, e);
}
/// <summary>
/// Paints the background of the control
/// </summary>
/// <param name="e">A PaintEventArgs object that contains event data</param>
protected override void OnPaintBackground(PaintEventArgs e)
{
// do not use arg, because can't control back/screen
Graphics gfx = CreateGraphics();
gfx.Clear(BackColor);
gfx.Dispose();
}
/// <summary>
/// Raises the Resize event
/// </summary>
/// <param name="e">An EventArgs that represents event data</param>
protected override void OnResize(System.EventArgs e)
{
if (Size != oldSize) // Stupid control gets resized when like anything happens to the parent form
{
if (doubleBuffered)
{
if (backBuffer != null)
backBuffer.Dispose();
backBuffer = new Bitmap(Width != 0 ? Width : 1, Height != 0 ? Height : 1);
}
}
oldSize = Size;
base.OnResize(e);
}
/// <summary>
/// Creates the Graphics for the control
/// </summary>
/// <param name="backBuffer">True to bypass the buffer and get the control graphics</param>
/// <returns></returns>
public virtual Graphics CreateGraphics(bool bypass)
{
if(bypass || !doubleBuffered)
return base.CreateGraphics();
else
return Graphics.FromImage(backBuffer);
}
public virtual new Graphics CreateGraphics()
{
return CreateGraphics(false);
}
}
并且您将需要这些:
/// <summary>
/// Provides data for the DoubleBufferedControl.Paint event
/// </summary>
public class DoubleBufferedPaintEventArgs : PaintEventArgs
{
/// <summary>
/// Initializes a DoubleBufferedPaintEventArgs
/// </summary>
/// <param name="g">The Graphics object to paint to; If the control is double buffered, the graphics object is for the buffer otherwise the screens graphics is used</param>
/// <param name="clip">The region in which to paint</param>
public DoubleBufferedPaintEventArgs(Graphics g, Rectangle clip) : base(g, clip) { }
}
public delegate void BufferedPaintEventHandler(object sender, DoubleBufferedPaintEventArgs args);
我通常从此类继承,重写OnPaintBackground
方法,并将其实现保留为空白。 然后,我在OnPaint方法中实现所有自定义绘图。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.