![enter image description here](https://i.stack.imgur.com/W12m8.png)
Мой первоначальный подход к этому заключался в использовании GetSystemMetrics
с SystemMetric.SM_CXSIZE
и некоторой простой математике, основанной на доступных кнопках (3 раза или 1). через WindowStyle
.
[DllImport("user32.dll")]
private static extern int GetSystemMetrics(SystemMetric smIndex);
Это имеет проблему на Windows 10, где расчетная ширина составляет приблизительно 70% от фактической. Так что ширина охватывает всего две кнопки - развернуть и закрыть. Windows 7 и 8.1 в порядке, тот же параметр DPI, где он охватывает все кнопки.
Я проверил несколько существующих вопросов о переполнении стека, и больше всего с этим справился в 2011 году:
К сожалению, хотя предлагаемый подход *1023* работает в windows 8.1 рассчитывает 0 на Windows 10 (последняя версия, все рекомендуемые обновления). Есть ли способ, который работает на всех ОС от 7 до 10?
Код был взят из приведенного выше ответа и изменен для вычисления общей ширины кнопок управления окном, с помощью дескриптора окна (hwnd), и изменил маршаллинг на RECT из Rectangle (тогда я получаю правильные значения влево / вправо).
public static int GetControlButtonsWidth(IntPtr hwnd)
{
// Create and initialize the structure
TITLEBARINFOEX tbi = new TITLEBARINFOEX();
tbi.cbSize = Marshal.SizeOf(typeof(TITLEBARINFOEX));
// Send the WM_GETTITLEBARINFOEX message
SendMessage(hwnd, WM_GETTITLEBARINFOEX, IntPtr.Zero, ref tbi);
int sum = tbi.rgrect.Sum(r => r.right - r.left);
// Return the filled-in structure
return sum;
}
internal const int WM_GETTITLEBARINFOEX = 0x033F;
internal const int CCHILDREN_TITLEBAR = 5;
[StructLayout(LayoutKind.Sequential)]
internal struct TITLEBARINFOEX
{
public int cbSize;
public RECT rcTitleBar;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = CCHILDREN_TITLEBAR + 1)]
public int[] rgstate;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = CCHILDREN_TITLEBAR + 1)]
public RECT[] rgrect;
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern IntPtr SendMessage(
IntPtr hWnd,
int uMsg,
IntPtr wParam,
ref TITLEBARINFOEX lParam);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left, top, right, bottom;
}