.NET Compact Framework上的双重缓冲 [英] Double buffering on .NET Compact Framework

查看:97
本文介绍了.NET Compact Framework上的双重缓冲的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否有人可以向我解释如何在.net紧凑框架中对完整表单进行双重缓冲.我已经找到了双缓冲的示例,但似乎无法使它们发挥任何作用.

I was wondering if someone could explain to me how to double buffer a complete form in .net compact framework. I've found examples of double buffering but I can't seem to get any of these to work.

我们创建了具有多种形式的应用程序.其中一些表格确实需要很长时间才能在屏幕上绘制,从而导致闪烁.为了让您对我们的应用程序有一些了解,我将解释其中一种形式. 该表单包含一个usercontrol,一些面板,文本框和按钮. 用户控件的面板具有自定义绘图(在屏幕上绘制文本和图像(具有透明性)).甚至这些面板中的某些面板都包含其他可做相同事情的面板. 面板还具有自定义绘图,因为我们在屏幕上绘制了带有某些效果等的文本. 每个面板需要花费一些时间来绘制,这意味着如果我们在3x3的网格中有9个面板,它们将被绘制并以随机顺序显示,而不是同时显示所有beeing.文本绘图等也是如此.我们希望同时显示表单上的所有内容.

We created an application with multiple forms. Some of these forms do take a long time to draw on screen which results in flickering. To give you some insight into our application i'm going to explain one of the forms. This form contains a usercontrol , some panels, textboxes and buttons. The usercontrol has panels that have custom drawing (drawing text and images (with transparancy) on screen). And even some of these panels contain other panels that do the same thing. The panels also have custom drawing because we draw text on screen with some effects, etc. Each panel takes time to be drawn, which means if we have 9 panels in a 3x3 grid, they get drawn and show in random order, instead of beeing displayed all at the same time. Same happens with the text drawing, etc. We would like to have everything on the form to be displayed at the same time.

所以我的问题是,我可以创建一个执行双缓冲的'super'类吗,是否将图形保存在完整形式的内存中?

So my question is, can i create a 'super' class that does the double buffering, do the drawing in memory of the complete form?

我可以在不更改控件,面板,图像绘制等任何内容的情况下扩展当前表格吗?

Can i extend my currect forms from it without having to change anything to my controls, panels, drawing of images, etc?

谢谢

推荐答案

我不确定带有所有控件的确切形式的复杂性,但是我已经实现了一个基本的DoubleBufferableControl类,可以扩展它以创建双缓冲的自定义控件.我用自定义图形创建了许多控件,所有控件都以此为基类.

I'm not sure about the intricacies of your exact form with all the controls on it, but I've implemented a base DoubleBufferableControl class from which you can extend it to create custom controls that are double buffered. I've created many controls with custom drawing which all use this as a base class.

您可以使用此类作为控件的基类,这些控件具有自定义绘画以避免闪烁.在子类中,请确保在构造函数中将DoubleBuffered设置为true.

You can use this class as the base class of your controls which have custom painting to avoid flickering. In your child class be sure to set DoubleBuffered to true in the constructor.

    /// <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方法实现所有自定义绘图.

I typically inherit from this class, override the OnPaintBackground method and leave its implementation blank. Then, I implement all of the custom drawing in the OnPaint method.

这篇关于.NET Compact Framework上的双重缓冲的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆