首页 > 解决方案 > 将 TabControl 和 Form 宽度动态调整为 TabPage 的数量

问题描述

我有一个带有 TabControl 和 ListView 的窗体。
当我运行应用程序时,我希望WidthTabControl 增加/减少以显示所有没有水平滚动条的 TabPages 并相应地调整 Form 的大小Width,以确保 TabControl 和 ListView 可见。

截图如下。

在此处输入图像描述

标签: c#winformstabcontrolautosize

解决方案


要将 TabControl 的大小自动调整为其 Headers 的大小,您需要计算每个 Header 的文本宽度。如果将TabControl.SizeMode设置为Fixed会更简单,因为您可以设置ItemSize.Width并且所有 Headers 将具有相同的宽度。

如果TabControl.SizeMode设置为默认值Normal,则必须测量每个标题的文本,添加1px边框(2px如果它是第二个 TabPage - 基本控件中的小错误)。

在第一种情况下,TabControl 的大小为:

tabControl1.Width = tabControl1.TabPages.Count * (tabControl1.ItemSize.Width + 1);

在第二种情况下,使用TextRendrer.MeasureText测量每个 Header 的文本:

private int MeasureTabPagesWidth(TabControl tc)
{
    if (tc.TabPages.Count == 0) return tc.Width;
    int newWidth = 0;
    int border = tc.TabPages.Count == 2 ? 2 : 1;
    var flags = TextFormatFlags.LeftAndRightPadding;

    using (var g = tc.CreateGraphics()) {
        foreach (TabPage tab in tc.TabPages) {
            newWidth += TextRenderer.MeasureText(g, tab.Text, tc.Font, 
                new Size(int.MaxValue, tc.Font.Height + 4), flags).Width + border;
        }
    }
    return newWidth;
}

设置布局

  • 将 TableLayoutPanel 添加到您的表单中,其中包含一行和两列(即,删除一行)
  • 将 TabControl 添加到左侧的单元格,将 ListBox 添加到另一个单元格。
  • 将两个单元格的样式设置为AutoSize(添加控件后)。
  • 将 TableLayoutPanel 设置为: AutoSize = true,AutoSizeMode = GrowAndShrink
  • 以相同的方式将表单设置为自动调整大小
  • 设置表单的MinimumSizeMaximumSize。前者通常设置为设计尺寸,后者由您决定;您可以使用当前的Screen WorkingArea作为参考。
  • 在创建或加载 Form 时计算 TabControl 的新宽度(即在其 Constructor 或OnLoad()or中Form.Load),因此 Form 将自动调整为 TableLayoutPanel 的大小,而后者又会自动调整为其子项的大小控制。

现在您可以在运行时添加或删除 TabPages,并且表单将自动调整为您在TabControl.ControlAddedTabControl.ControlRemoved事件处理程序中计算的宽度(同时检查添加的控件是否属于 Type TabPage)。

示例

  • MeasureTabPagesWidth()方法是上面显示的方法。
  • TableLayoutPanel 被命名为tlp1
  • TabControl 被命名为tabControl1
  • 视觉示例中使用的按钮具有定义其角色的名称。
public partial class AutoSizeForm : Form
{
    public AutoSizeForm()
    {
        InitializeComponent();
        tabControl1.Width = MeasureTabPagesWidth(tabControl1);
    }

    private void tabControl1_ControlAdded(object sender, ControlEventArgs e)
    {
        // Event notified after the TabPage has been added
        if (e.Control is TabPage) {
            tabControl1.Width = MeasureTabPagesWidth(tabControl1);
        }
    }

    private void tabControl1_ControlRemoved(object sender, ControlEventArgs e)
    {
        if (e.Control is TabPage) {
            // Use deferred execution, since the TabPage is removed after 
            // the event handler method completes.
            BeginInvoke(new Action(()=> tabControl1.Width = MeasureTabPagesWidth(tabControl1)));
        }
    }

    private void btnAddPage_Click(object sender, EventArgs e) 
    {
        tabControl1.TabPages.Add(new TabPage("New TabpPage Text"));
    }

    private void btnRemovePage_Click(object sender, EventArgs e)
    {
        if (tabControl1.TabPages.Count > 0) {
            tabControl1.TabPages.RemoveAt(tabControl1.TabPages.Count - 1);
        }
    }

    private void btnAddCtlToTLP_Click(object sender, EventArgs e)
    {
        tlp1.ColumnCount += 1;
        tlp1.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
        var mc = new MonthCalendar();
        tlp1.SetColumn(mc, tlp1.ColumnCount - 1);
        tlp1.Controls.Add(mc);
    }
}

它是这样工作的:
在 Windows 7 中测试,因为这似乎是正在使用的系统

窗体 TabControl AutoSize

示例项目
Google Drive 上的示例项目 ( .Net Framework 4.8- C# 7.3)
在运行之前重新构建解决方案


推荐阅读