In the last few months, my Windows captions look something like this:
The caption buttons are not square. Someone asked me how I did it…
Well, Windows UI (Personalize…, etc.) allows changing the size of the caption buttons, but the width must be the same as the height. To make the caption buttons rectangular, one needs to call the SystemParametersInfo native API. Here’s some C++ code that does what you see here (width = 3 times height):
NONCLIENTMETRICS metrics = { sizeof(metrics) };
::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof (metrics), &metrics, 0);
metrics.iCaptionWidth = metrics.iCaptionHeight * 3;
::SystemParametersInfo(SPI_SETNONCLIENTMETRICS, sizeof(metrics), &metrics, 0);
To do the same with .NET, some interop is required:
[DllImport("user32", CharSet = CharSet.Auto)]
private static extern int SystemParametersInfo(int uAction, int uParam, ref NONCLIENTMETRICS lpvParam, int fuWinIni);
private const int LF_FACESIZE = 32;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct LOGFONT {
public int lfHeight;
public int lfWidth;
public int lfEscapement;
public int lfOrientation;
public int lfWeight;
public byte lfItalic;
public byte lfUnderline;
public byte lfStrikeOut;
public byte lfCharSet;
public byte lfOutPrecision;
public byte lfClipPrecision;
public byte lfQuality;
public byte lfPitchAndFamily;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = LF_FACESIZE)]
public string lfFaceName;
public LOGFONT(string lfFaceName) {
this.lfFaceName = lfFaceName;
lfHeight = lfWidth = lfEscapement = lfOrientation = lfWeight = 0;
lfItalic = lfUnderline = lfStrikeOut = lfCharSet =
lfOutPrecision = lfClipPrecision = lfQuality =
lfPitchAndFamily = 0;
}
}
private struct NONCLIENTMETRICS {
public int cbSize;
public int iBorderWidth;
public int iScrollWidth;
public int iScrollHeight;
public int iCaptionWidth;
public int iCaptionHeight;
public LOGFONT lfCaptionFont;
public int iSMCaptionWidth;
public int iSMCaptionHeight;
public LOGFONT lfSMCaptionFont;
public int iMenuWidth;
public int iMenuHeight;
public LOGFONT lfMenuFont;
public LOGFONT lfStatusFont;
public LOGFONT lfMessageFont;
}
private const int SPI_GETNONCLIENTMETRICS = 41;
private const int SPI_SETNONCLIENTMETRICS = 42;
static void Main(string[] args) {
NONCLIENTMETRICS metrics = new NONCLIENTMETRICS();
metrics.cbSize = Marshal.SizeOf(metrics);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, ref metrics, 0);
metrics.iCaptionWidth = 3 * metrics.iMenuHeight;
SystemParametersInfo(SPI_SETNONCLIENTMETRICS, 0, ref metrics, 0);
}
Not pretty… but can’t be helped.
There is a class, System.Windows.Forms.SystemInformation that exposes most of these values, but all as read-only.
You may have to “refresh” the caption to see the change, e.g. minimize & restore windows.