根据标题栏中的文本设置表单的宽度

Setting form's width according to text in title bar

当(或之后)调用我的 Form.Show() 方法时,我想根据标题栏中的字符串 (Form.Text) 设置表单的宽度(或最小宽度),因为此文本根据用户的选择而变化。表单宽度最终应该是完美的宽度,这样标题栏文本就不会被截断并以“...”结尾。
目前,我只是将 MinimumSize 属性 设置为适合所有选择的值,但自动调整大小看起来会稍微整洁一些。我的问题是标题栏文本没有任何属性来获取其实际宽度。 AutoSize 也只是根据表单中的控件改变大小。

有什么我可以做的吗?

你可以得到系统菜单的宽度,标题文本的宽度和控制框按钮的宽度,然后计算出首选宽度,并检查当前宽度是否小于首选宽度,然后更改宽度首选宽度。

要获取有关标题栏元素的信息,您可以发送包含有关标题栏信息的 WM_GETTITLEBARINFOEX message to window and get an instance of TITLEBARINFOEX 结构。

您还可以使用 SystemInformation.CaptionButtonSize to get control button sizes and SystemInformation.SmallIconSize 获取系统菜单图标大小并添加一些额外的填充 space。

例子

您可以覆盖如下形式的 OnShown 方法:

protected override void OnShown(EventArgs e)
{
    base.OnShown(e);

    var info = NativeMethods.GetTitleBarInfo(this.Handle);
    var systemMenuWidth = info.rcTitleBar.Left - this.Left;
    var controlBoxWidth =
        info.rgrect[(int)NativeMethods.TitleBarRectangles.CloseButton].Right -
        info.rgrect[(int)NativeMethods.TitleBarRectangles.MinimizeButton].Left;
    var titleWidth = TextRenderer.MeasureText(this.Text, SystemFonts.CaptionFont).Width;

    //var preferred = titleWidth + systemMenuWidth + controlBoxWidth + 16;
    //if (this.Width < preferred)
    //   this.Width = preferred;

    var preferred = titleWidth + systemMenuWidth + controlBoxWidth;
    if (this.Width < preferred)
        this.ClientSize = new Size(preferred, this.ClientSize.Height);
}

这里是 NativeMethods:

using System;
using System.Drawing;
using System.Runtime.InteropServices;

public static class NativeMethods
{
    public const int WM_GETTITLEBARINFOEX = 0x033F;
    public static TITLEBARINFOEX GetTitleBarInfo(IntPtr hwnd)
    {
        var info = new TITLEBARINFOEX()
        { cbSize = (uint)Marshal.SizeOf(typeof(TITLEBARINFOEX)) };
        SendMessage(hwnd, WM_GETTITLEBARINFOEX, IntPtr.Zero, ref info);
        return info;
    }
    [System.Runtime.InteropServices.DllImport("user32.dll")]
    static extern IntPtr SendMessage(
        IntPtr hWnd, int Msg, IntPtr wParam, ref TITLEBARINFOEX lParam);

    [StructLayout(LayoutKind.Sequential)]
    public struct TITLEBARINFOEX
    {
        public const int CCHILDREN_TITLEBAR = 5;
        public uint cbSize;
        public RECT rcTitleBar;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = CCHILDREN_TITLEBAR + 1)]
        public uint[] rgstate;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = CCHILDREN_TITLEBAR + 1)]
        public RECT[] rgrect;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct RECT
    {
        public int Left, Top, Right, Bottom;
        public Rectangle ToRectangle() => Rectangle.FromLTRB(Left, Top, Right, Bottom);
    }
    public enum TitleBarRectangles
    {
        TitleBar = 0,
        Reserved = 1,
        MinimizeButton = 2,
        MaximizeButton = 3,
        HelpButton = 4,
        CloseButton = 5
    }
}

所以在设计器中有这样的表格:

但在运行时:

替代解决方案 - 为标题栏设置工具提示

作为替代解决方案,您可以 add a ToolTip to the Form titlebar: