【问题标题】:How can I control the display order of child Forms in a MDI Form如何控制 MDI 表单中子表单的显示顺序
【发布时间】:2019-04-12 13:21:04
【问题描述】:

当我使用MDI 表单时,我遇到了问题。我的源代码是这样的:

private void menuItem1_Click(object sender, EventArgs e)
    {
        Form[] charr = this.MdiChildren;
        int i = 0;            
        foreach (Form chform in charr)
        {
            chform.Dock = DockStyle.Top;                
        }
        this.LayoutMdi(System.Windows.Forms.MdiLayout.TileHorizontal);
    }

子窗体的个数大于3。为了在调用LayoutMdi() 方法后正确显示它们,我必须将所有子窗体的Dock 属性设置为DockStyle.Top

调用LayoutMdi(MdiLayout.TileHorizontal)后,点击第一个子Form的标题栏,这个子Form自动显示在MDI父窗体的底部。

我希望单击的子窗体保持其原始位置。
对这个问题有什么想法吗?

【问题讨论】:

  • 只调用this.LayoutMdi(MdiLayout.TileHorizontal)而不对接MDI Children?
  • @Jimi 如果只调用 this.LayoutMdi(MdiLayout.TileHorizo​​ntal),它就不能正常工作。 stackoverflow.com/questions/50691902/…

标签: c# winforms display mdi


【解决方案1】:

查看链接的问题 - 建议设置 Dock 属性以调整 MDIChild 表单位置 - 以及当前报告的行为,最好将布局定义为 MDIChild 表单而不使用自动功能的帮助。

这允许执行任何看起来合适的布局逻辑。

在示例中,MDIChildren.Height 是相对于 MDIParent.ClientSize.Height 和打开的数量 MDIChildren 计算得出的,然后乘以一个值:在示例代码中乘以 2,是基本度量的两倍。

这个乘数允许相当精确地定义MDICHildrenHorizontal Tile Height。当然,您可以实现一些其他逻辑,仅当至少有 3 个打开的 MDIChildren 时才应用乘数。

所有MDIChildren 都重新调整大小以匹配MDIParent.Width 和计算出的Height,然后按名称排序并从上到下定位。

设置HorizontalTileHeightMultiplier 的不同值以查看MDIChildrenMDIParent.ClientArea (MdiClient) 中的位置。
此乘数还可用作应用程序中的自定义属性,供其用户使用,从而允许自定义平铺表单。

布局代码是作为私有方法提供的,因此可以在不同的事件处理程序中轻松使用它来执行/维护选定的布局(例如MDIParent.Resize)。
如果需要,此方法也可以轻松调整以替换 MdiLayout.TileVertical

private float HorizontalTileHeightMultiplier = 2;

private void menuItem1_Click(object sender, EventArgs e)
{
    TileHorizontal()
}

private void TileHorizontal()
{
    int OpenedForms = Application.OpenForms.Count - 1;
    if (OpenedForms < 2) return;

    int StartLocation = 0;
    int ChildrenHeight = 
        (int)((this.ClientSize.Height / OpenedForms) * HorizontalTileHeightMultiplier);

    List<Form> children = this.MdiChildren.OrderBy(f => f.Name).ToList();
    foreach (Form child in children)
    {
        child.Size = new Size(this.ClientSize.Width - SystemInformation.VerticalScrollBarWidth - 4, ChildrenHeight);
        child.Location = new Point(0, StartLocation);
        StartLocation += ChildrenHeight;
    }
}

【讨论】:

  • 感谢您的回答。我会试试的。
  • 我试过了,很有效!正如您所说,自动功能是导致此问题的原因(但是如何,我还不知道)。再次感谢您。
  • @ballshark 阅读我写的on this answer关于停靠/锚定时对象布局规则的描述,特别是与BringToFront/SendToBack行为有关的描述。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-23
相关资源
最近更新 更多