计算Windows 10上第三方窗口标题栏按钮的总宽度

问题描述 投票:1回答:1

enter image description here

[我最初的解决方法是将GetSystemMetricsSystemMetric.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;
}
c# winforms winapi window pinvoke
1个回答
1
投票

您可以使用DwmGetWindowAttribute,这三个按钮的组合宽度在Windows 10上应为185像素,DPI为125%。请注意,如果您的应用程序不支持DPI,则结果仍将相同,例如185。

DwmGetWindowAttribute
© www.soinside.com 2019 - 2024. All rights reserved.