You can get the width of the system menu, width of the title text and width of control box buttons, then calculate the preferred width and check if the current width is less that the preferred with, then change the widths of the for to preferred width.
To get the information about titlebar elements, you can send a WM_GETTITLEBARINFOEX message to window and get an instance of TITLEBARINFOEX structure which contains information about titlebar.
You can also use SystemInformation.CaptionButtonSize to get control button sizes and SystemInformation.SmallIconSize to get system menu icon size and add a bit of extra padding space.
Example
You can override OnShown method of the form like this:
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);
}
And here is 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
}
}
So having such form in designer:
But at runtime:
Alternative solution - Set tooltip for titlebar
As an alternative solution you can add a ToolTip to the Form titlebar:
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…