c# - 将 TabControl 和 Form 宽度动态调整为 TabPage 的数量
问题描述
我有一个带有 TabControl 和 ListView 的窗体。
当我运行应用程序时,我希望Width
TabControl 增加/减少以显示所有没有水平滚动条的 TabPages 并相应地调整 Form 的大小Width
,以确保 TabControl 和 ListView 可见。
截图如下。
解决方案
要将 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
- 以相同的方式将表单设置为自动调整大小
- 设置表单的MinimumSize和MaximumSize。前者通常设置为设计尺寸,后者由您决定;您可以使用当前的Screen WorkingArea作为参考。
- 在创建或加载 Form 时计算 TabControl 的新宽度(即在其 Constructor 或
OnLoad()
or中Form.Load
),因此 Form 将自动调整为 TableLayoutPanel 的大小,而后者又会自动调整为其子项的大小控制。
现在您可以在运行时添加或删除 TabPages,并且表单将自动调整为您在TabControl.ControlAdded和TabControl.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 中测试,因为这似乎是正在使用的系统
示例项目:
Google Drive 上的示例项目 ( .Net Framework 4.8
- C# 7.3
)
在运行之前重新构建解决方案
推荐阅读
- spring-boot - 无法使用 @GeneratedValue(IDENTITY) 和双向 @OneToMany 将对象保存到数据库
- django - 在 head 标签内渲染 django-recaptcha 的脚本标签
- node.js - 在 WSL Ubuntu 20.04 上安装 npm 后,我收到消息“/usr/bin/env: 'bash\r': No such file or directory”
- postgresql - 在 JOOQ 的 IN 子句中使用 Postgres VALUES 函数
- unity3d - unity 2021 无法创建单个 Tile 或可以但文档让我感到困惑
- c# - 强制规范流测试失败
- javascript - 使用 ThreeJS 进行世界旋转
- java - Java 方法只是停止运行
- crystal-reports - Crystal Reports - 如果详细信息部分为空,如何抑制页眉?
- c++ - C++ 比较运算符重载 const 与非 const 行为