计算 Windows 10 上第 3 方窗口的标题栏按钮的总宽度 [英] Compute total width of title bar buttons for 3rd party window on windows 10

查看:66
本文介绍了计算 Windows 10 上第 3 方窗口的标题栏按钮的总宽度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最初的方法是使用 GetSystemMetricsSystemMetric.SM_CXSIZE 和一些基于可用按钮(次数 3 或次数 1)的简单数学运算,通过 WindowStyle.

My initial approach to this was using GetSystemMetrics with SystemMetric.SM_CXSIZE and some simple math based on which buttons are available (times 3, or times 1), via WindowStyle.

[DllImport("user32.dll")]
private static extern int GetSystemMetrics(SystemMetric smIndex);

这在 Windows 10 上存在问题,其中计算出的宽度约为实际宽度的 70%.所以宽度只覆盖两个按钮 - 最大化和关闭.Windows 7 和 8.1 很好,相同的 DPI 设置,它涵盖了所有按钮.

This has an issue on Windows 10, where the calculated width is approximately 70% of actual. So the width covers just two buttons - maximize and close. Windows 7 and 8.1 are fine, same DPI setting, where it covers all buttons.

我检查了 Stack Overflow 上的一些现有问题,并且在 2011 年的这个问题上取得了最大成功:

I checked a few existing questions on Stack Overflow, and had most success with this one from 2011:

不幸的是,虽然建议的方法在 Windows 8.1 中确实有效,但它在 Windows 10(最新版本,所有推荐更新).有没有一种方法适用于从 7 到 10 的所有操作系统?

Unfortunately, while the suggested approach does work in windows 8.1, it calculates 0 on Windows 10 (latest version, all recommended updates). Is there a way that works on all OS from 7 to 10?

代码取自上述答案并修改为通过窗口句柄 (hwnd) 计算窗口控制按钮的总宽度,并将编组从 Rectangle 更改为 RECT(然后我得到正确的左/右值).

Code was taken from the above answer and modified to calculate total width of window's control buttons, by window handle (hwnd), and changed marshalling to RECT from Rectangle (then I get correct values of 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 上,这 3 个按钮的组合宽度应为 185 像素,DPI 为 125%.请注意,如果您的应用程序不支持 DPI,那么结果仍然相同,例如 185.

You can use DwmGetWindowAttribute, the combined width for those 3 buttons should be 185 pixels on Windows 10, at 125% DPI. Note that if your application is not DPI aware, then the result will still be the same, 185 for example.

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
    public int left;
    public int top;
    public int right;
    public int bottom;
}

[DllImport("dwmapi.dll")]
public static extern int DwmGetWindowAttribute(
    IntPtr hwnd, int attr, out RECT ptr, int size);

public void foo()
{
    int DWMWA_CAPTION_BUTTON_BOUNDS = 5;
    RECT rc;
    if (0 != DwmGetWindowAttribute(this.Handle, DWMWA_CAPTION_BUTTON_BOUNDS,
        out rc, Marshal.SizeOf(typeof(RECT))))
    {
        //error
    }
    int width = rc.right - rc.left;
}

这篇关于计算 Windows 10 上第 3 方窗口的标题栏按钮的总宽度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆