WindowsForm-调整大小后闪烁

时间:2018-08-02 08:14:54

标签: c# winforms flicker

我有一个WinForm应用程序(启用了双缓冲区),其中的TableLayoutPanel包含一些DataGridView,一些ActiveX控件(来自NI TestStand)和一些标签。我在Form CellPaint事件中添加了一些代码以在需要的地方绘制边框。

一个标签通过Systems.Windows.Forms.Timer显示实际的DateTime,每秒递增一次。每次更新时,表格都会闪烁。如果我在CellPaint事件中注释了代码,则闪烁停止。

添加:

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

解决了启用CellPaint代码的闪烁问题,但前提是我不调整表单大小。调整大小后,闪烁开始并且永不停止。

我尝试了一些在SO上找到的建议,但是没有运气,因为建议here暂停了布局,使用反射在每个控件上启用了双重缓冲。

如何在调整大小后也避免闪烁?

编辑: 以下是与Cellpaint事件相关的代码:

private void LayoutMainWindow_CellPaint(object sender, TableLayoutCellPaintEventArgs e)
{
    SuspendLayout();
    if (e.Row == 0 && e.Column > 0)
    {
        DrawBottomBorder(e, 1);
    }
    if (e.Row == 1 && e.Column != 0)
    {
        DrawBottomBorder(e, 2);
    }
    if (e.Row <= 8 && e.Column == 0)
    {
        DrawRightBorder(e, 2);
    }
    if (e.Row == 2 && e.Column == 0)
    {
        DrawBottomBorder(e, 2);
    }
    if ((e.Row >= 2 && e.Row <= 7) && e.Column == 2)
    {
        DrawRightBorder(e, 2);
    }
    if (e.Row == 7 && e.Column <= 4)
    {
        DrawBottomBorder(e, 2);
    }
    if (e.Row >= 8 && e.Row <= 9)
    {
        DrawBottomBorder(e, 2);
    }
    if (e.Row == 9 && e.Column == 0)
    {
        DrawRightBorder(e, 2);
    }
    ResumeLayout();
}

private static void DrawRightBorder(TableLayoutCellPaintEventArgs e, float width)
{
    Rectangle r = e.CellBounds;
    using (Pen pen = new Pen(Color.Gray, width))
    {
        e.Graphics.DrawLine(pen, r.X + r.Width, r.Y, r.X + r.Width, r.Y + r.Height);
    }
}

private static void DrawBottomBorder(TableLayoutCellPaintEventArgs e, float width)
{
    Rectangle r = e.CellBounds;
    using (Pen pen = new Pen(Color.Gray, width))
    {
        e.Graphics.DrawLine(pen, r.X, r.Y + r.Height, r.X + r.Width, r.Y + r.Height);
    }
}

1 个答案:

答案 0 :(得分:2)

感谢TaW建议,因为CellPaint与包含Form内所有控件的TableLayout有关:

private static void SetDoubleBuffered(Control c)
{
    if (System.Windows.Forms.SystemInformation.TerminalServerSession)
        return;
    System.Reflection.PropertyInfo aProp = typeof(System.Windows.Forms.Control).GetProperty("DoubleBuffered",
    System.Reflection.BindingFlags.NonPublic |
    System.Reflection.BindingFlags.Instance);
    aProp.SetValue(c, true, null);
}

然后:

SetDoubleBuffered(LayoutMainWindow);

它解决了我的问题。非常感谢你们。