* UIStatusForm: 优化多行文本显示时的布局调整,支持任意行数的文本内容显示。

This commit is contained in:
yhuse
2025-11-29 09:00:13 +08:00
parent 6574af28a9
commit f849278b53

View File

@@ -18,9 +18,12 @@
*
* 2020-05-05: V2.2.5 增加文件
* 2025-09-15: V3.8.8 进度提示框增加取消功能。#IA5Q0Z
* 2025-11-29: V3.9.0 优化多行文本显示时的布局调整,支持任意行数的文本内容显示。
******************************************************************************/
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace Sunny.UI
{
@@ -119,10 +122,120 @@ namespace Sunny.UI
else
{
labelDescription.Text = text;
// 动态调整布局以适应多行文本
AdjustLayoutForMultiLineText();
labelDescription.Invalidate();
}
}
/// <summary>
/// 根据文本内容动态调整布局,确保多行文本(任意行数)不被进度条遮住
/// <para>实现方式:</para>
/// <para>1. 计算文本实际需要的高度(考虑换行,支持任意行数)</para>
/// <para>2. 动态调整 labelDescription 的高度以适应文本内容</para>
/// <para>3. 动态调整 processBar 的位置,确保在 labelDescription 下方</para>
/// <para>4. 自动增加窗体高度以容纳所有内容(无论多少行)</para>
/// <para>5. 单行文本时恢复默认布局</para>
/// </summary>
private void AdjustLayoutForMultiLineText()
{
try
{
if (string.IsNullOrEmpty(labelDescription.Text))
{
// 空文本时恢复默认布局
RestoreDefaultLayout();
return;
}
// 计算文本实际需要的高度(考虑换行,支持任意行数)
// labelDescription 的可用宽度:窗体宽度 - 左右边距32*2
int labelWidth = this.ClientSize.Width - 32 * 2;
if (labelWidth <= 0)
{
labelWidth = 409 - 32 * 2; // 使用默认宽度
}
// 使用 TextRenderer.MeasureText 计算文本高度(更准确,支持换行和任意行数)
// 使用 int.MaxValue 作为高度限制,确保能够测量所有行
Size textSize = TextRenderer.MeasureText(
labelDescription.Text,
labelDescription.Font,
new Size(labelWidth, int.MaxValue),
TextFormatFlags.WordBreak | TextFormatFlags.TextBoxControl | TextFormatFlags.NoPrefix);
// 计算单行文本的高度(用于判断是否需要调整)
int singleLineHeight = TextRenderer.MeasureText("A", labelDescription.Font).Height;
// 如果文本高度超过单行高度,说明是多行文本,需要调整布局
if (textSize.Height > singleLineHeight)
{
// 计算 labelDescription 需要的实际高度(加上一些边距以确保显示完整)
const int verticalPadding = 4; // 上下各2像素边距
int labelHeight = textSize.Height + verticalPadding;
// 设置 labelDescription 的高度和宽度(取消 AutoSize 的固定高度限制)
labelDescription.AutoSize = false;
labelDescription.Width = labelWidth;
labelDescription.Height = labelHeight;
// 调整 processBar 的位置,确保在 labelDescription 下方,留出适当间距
const int spacing = 10; // labelDescription 和 processBar 之间的间距
int newProcessBarTop = labelDescription.Top + labelHeight + spacing;
// 计算窗体需要的最小高度
// 顶部边距55 + labelDescription高度 + 间距 + processBar高度 + 底部边距
const int topMargin = 55; // labelDescription 的 Top 位置
const int bottomMargin = 20; // 底部边距
int minFormHeight = topMargin + labelHeight + spacing + processBar.Height + bottomMargin;
// 确保窗体高度足够容纳所有内容
if (minFormHeight > this.ClientSize.Height)
{
// 调整窗体高度
this.ClientSize = new Size(this.ClientSize.Width, minFormHeight);
}
// 调整 processBar 的位置
processBar.Top = newProcessBarTop;
}
else
{
// 单行文本,恢复默认布局
RestoreDefaultLayout();
}
}
catch
{
// 如果调整失败,尝试恢复默认布局
try
{
RestoreDefaultLayout();
}
catch
{
// 如果恢复也失败,保持当前状态
}
}
}
/// <summary>
/// 恢复默认布局(单行文本时的布局)
/// </summary>
private void RestoreDefaultLayout()
{
// 恢复 labelDescription 的 AutoSize
labelDescription.AutoSize = true;
// 恢复 processBar 的默认位置
processBar.Top = 91;
// 恢复窗体的默认高度
this.ClientSize = new Size(473, 153);
}
private delegate void StepItHandler(int step);
public void StepIt(int step = 1)