[我最初的解决方法是将GetSystemMetrics
与SystemMetric.SM_CXSIZE
结合使用,并根据通过WindowStyle
可用的按钮(时间3,或时间1)进行一些简单的数学运算。
[DllImport("user32.dll")]
private static extern int GetSystemMetrics(SystemMetric smIndex);
这在Windows 10上存在问题,在Windows 10上,计算出的宽度大约是实际宽度的70%。因此,宽度仅覆盖两个按钮-最大化和关闭。 Windows 7和8.1很好,DPI设置相同,其中包含所有按钮。
我检查了一些有关Stack Overflow的现有问题,并且从2011年开始使用此方法取得了最大的成功:
[不幸的是,虽然suggested approach在Windows 8.1中可以正常运行,但它在Windows 10(最新版本,所有建议的更新)上计算为0。有没有一种方法可以在从7到10的所有操作系统上运行?
代码是从以上答案中提取的,并通过窗口句柄(hwnd)进行了修改,以计算窗口控制按钮的总宽度,并将编组从Rectangle更改为RECT(然后我得到了正确的left / right值)。
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;
}
您可以使用DwmGetWindowAttribute
,这三个按钮的组合宽度在Windows 10上应为185像素,DPI为125%。请注意,如果您的应用程序不支持DPI,则结果仍将相同,例如185。
DwmGetWindowAttribute