【问题标题】:WindowsForm - Flicker after resizeWindows 窗体 - 调整大小后闪烁
【发布时间】:2019-01-09 22:29:21
【问题描述】:

我有一个带有 TableLayoutPanel 的 WinForm 应用程序(启用双缓冲区),其中包含一些 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);
    }
}

【问题讨论】:

  • 哪里有闪烁相关的代码?
  • 你不能指望winforms运行这个性能。它不是为此而生的。
  • @sLw:你不能指望winforms运行这个性能。嗯?你的意思是??每秒一屏更新太多了?废话!!
  • TableLayoutPanel 没有双缓冲,因此很容易解释来自 CellPainting 的闪烁。挖得更深一点,如果它连续闪烁,那么你会遇到一个讨厌的问题,即绘制事件一次又一次地触发。你现在隐瞒这个问题,不好。应该可以从任务管理器的“进程”选项卡中看到您的程序正在燃烧 100% 核心。当绘制事件处理程序再次导致绘制时发生。不太容易从 sn-p 中看出原因,可能是由 Suspend/ResumeLayout() 引起的。它们当然不属于绘制事件处理程序。
  • @HansPassant CellPaint 事件在启动时、每次调整大小时以及每一秒时触发,当包含 DateTime 的标签被更新时。我检查了,我没有占用 CPU。尽管如此,我还是按照您的建议删除了暂停/恢复布局。

标签: c# winforms flicker


【解决方案1】:

感谢 TaW 的建议,只要 CellPaint 与包含表单内所有控件的 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);

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

【讨论】:

  • 这对我来说也适用于大数据网格视图。我正在将属性添加到包含 DGV 的面板中,但将属性添加到 DGV 并闪烁结束。
猜你喜欢
  • 2019-02-27
  • 1970-01-01
  • 2010-11-22
  • 2015-08-29
  • 2014-12-29
  • 1970-01-01
  • 2019-12-06
  • 1970-01-01
  • 2016-03-19
相关资源
最近更新 更多