代码之家  ›  专栏  ›  技术社区  ›  dandan78 Tom Cool

mdi子窗体在可见性更改时绘制速度较慢

  •  3
  • dandan78 Tom Cool  · 技术社区  · 15 年前

    我的应用程序具有以下UI配置:

    主要形式是MDI容器。它的子窗体附加到 TabStrip

    每个用户都有自己的子窗体集。根据活动用户的不同,仅显示该用户的子窗体以及选项卡。

    这是通过检查主窗体的 MdiChildren Visible false/true 取决于活动用户。

            foreach (Form item in MdiChildren)
            {
                if (((OfficeFormEx)item).UserID == (int)e.NewTab.Tag)
                {
                    item.Visible = true;
                }
                else
                {
                    item.Visible = false;
                }
            }
    

    有没有办法只显示一个子窗体,比如用户以前看到的窗体,并让其他窗体留在后台?最大化/正常的事情没什么大不了的,因为我可以手动再次最大化它们。

    3 回复  |  直到 15 年前
        1
  •  2
  •   Hans Passant    15 年前

    如果没有代码片段,你的问题就不太清楚。但是,您正在与WindowsMDI实现进行斗争。它不支持的一件事是隐藏子窗口,它最多只能最小化。Windows窗体通过销毁窗口句柄来实现Visible属性,当Visible属性再次设置为True时重新创建它。窗口的新实例不会被最大化。

    当当前窗口最大化时,它也不支持将焦点切换到子窗口。WF的解决方法是强制活动子窗口恢复到正常状态。

        2
  •  2
  •   Will Marcouiller    15 年前

    乍一看,我会看看 Form.WindowsState 财产,如果你还没有的话。我怀疑如果你碰巧把这个属性设置为 FormWindowState.Maximized 在设计上,在设置 Visible true / false

    SuspendLayout() 方法,并调用 ResumeLayout() 后来呢?

    编辑#1

    • 我建议你只装所需的货物 Form

    这样做将减少应用程序所使用的内存量,此外,还将大大减少应用程序中包含的窗体数 MdiChildren 集合属性。然后,如果仍然需要,遍历集合的速度会更快。

    可能有帮助:

    var visibleForms = from f in MdiChildren
                       where (((OfficeFormEx)f).UserID == (int)e.NewTab.Tag)
                       select f;
    
    var invisibleForms = from f in MdiChildren
                         where (((OfficeFormEx)f).UserID != (int)e.NewTab.Tag)
                         select f
    
    visibleForms.ToList().ForEach(f => f.Visible = true);
    invisibleForms.ToList().ForEach(f => f.Visible = false);
    

    如果您使用的是.NET4.0,那么这可能是一个很好的选择 PLINQ

        3
  •  1
  •   dandan78 Tom Cool    15 年前

    我最终解决了这个问题,所以这里有一篇迟来的文章。

    威尔·马奎勒建议 SuspendLayout() ResumeLayout()

    这又导致了以下两个静态实用程序方法,它们暂停对给定控件的重绘。在我的例子中,主窗体的暂停重画导致了一个巨大的加速。

    /// <summary>
    /// suspends drawing on a control and its children
    /// </summary>
    /// <param name="parent"></param>
    public static void SuspendDrawing(Control control)
    {
        SendMessage(control.Handle, WM_SETREDRAW, false, 0);
    }
    
    /// <summary>
    /// resumes drawing on a control and its children
    /// </summary>
    /// <param name="parent"></param>
    public static void ResumeDrawing(Control control)
    {
        SendMessage(control.Handle, WM_SETREDRAW, true, 0);
        control.Refresh();
    }