如何在c#winforms中使用绘制方法时防止闪烁

本文关键字:方法 闪烁 绘制 c#winforms | 更新日期: 2023-09-27 18:14:36

代码:

private void panel1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.DrawRectangle(Pens.White,
    e.ClipRectangle.Left,
    e.ClipRectangle.Top,
    e.ClipRectangle.Width - 1,
    e.ClipRectangle.Height - 1);
    base.OnPaint(e);
}

如何避免闪烁。以上是Panel中Paint事件的panel1_Paint方法。谢谢

如何在c#winforms中使用绘制方法时防止闪烁

某些Windows窗体控件默认情况下没有启用双缓冲。我不确定面板是否是其中之一,但尝试启用它不会有什么坏处。

不幸的是,Control.DoubleBuffered是受保护的,所以除非你从控件继承,否则你必须求助于反射来启用它

Control ctrl;
ctrl.GetType()
    .GetProperty("DoubleBuffered", 
                 BindingFlags.Instance | BindingFlags.NonPublic)
    .SetValue(control, true, null);

问题很可能是由于没有启用双缓冲而引起的。双缓冲是先写入内部(不可见(缓冲区,直到所有绘制操作完成,然后将所述缓冲区闪电传输到可见缓冲区的过程,这通过简化实际缓冲区上的绘制操作来避免闪烁。

http://msdn.microsoft.com/en-us/library/3t7htc9c(v=vs.110(.aspx列出了可能的解决方案。将属性DoubleBuffered设置为true似乎是最简单的方法。然而,由于它是受保护的,您要么需要使用反射来访问它,要么从面板类继承,在您的新类中将其设置为true,然后使用所述新类:

public class myPanel : Panel {
    public myPanel() : base() {
        this.DoubleBuffered = true;
    }
}

有几种方法可以防止容器控件(如面板控件(闪烁。这些方法中的每一个都涉及从Panel基类(或其他合适的基类(派生

第一种方法是启用双缓冲,这可以使用以下代码行来实现:

this.DoubleBuffered = true;

第二种有效的方法是重写CreateParams属性并启用WS_EX_COMPOSITED。这是使用以下代码完成的:

private const int WS_EX_COMPOSITED = 0x02000000;
protected override CreateParams CreateParams
{
    get
    {
        CreateParams cp = base.CreateParams;
        cp.ExStyle |= WS_EX_COMPOSITED;
        return cp;
    }
} 

为了访问这两个属性中的任何一个,正如我们已经确定的,我们需要从基类派生。因此,整个类声明可能看起来像这样:

public class GraphicsPanel : Panel
{
    private const int WS_EX_COMPOSITED = 0x02000000;
    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= WS_EX_COMPOSITED;
            return cp;
        }
    }
    public GraphicsPanel()
    {
        this.DoubleBuffered = true;
    }
}

在重建我们的解决方案后,一个新的控件将被添加到名为GraphicsPanel的工具箱中,我们可以直观地设计它。在运行时,您应该注意到闪烁明显减少。