簡體   English   中英

計算 Windows 10 上第 3 方窗口的標題欄按鈕的總寬度

[英]Compute total width of title bar buttons for 3rd party window on windows 10

在此處輸入圖片說明

我最初的方法是使用GetSystemMetricsSystemMetric.SM_CXSIZE以及一些基於按鈕可用(3 次或 1 次)的簡單數學,通過WindowStyle

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

這在 Windows 10 上存在問題,其中計算出的寬度約為實際寬度的 70%。 所以寬度只覆蓋兩個按鈕 - 最大化和關閉。 Windows 7 和 8.1 很好,相同的 DPI 設置,它涵蓋了所有按鈕。

我檢查了 Stack Overflow 上的一些現有問題,並且從 2011 年開始在這個問題上取得了最大的成功:

不幸的是,雖然建議的方法在 Windows 8.1 中有效,但它在 Windows 10(最新版本,所有推薦更新)上計算為 0。 有沒有一種方法適用於從 7 到 10 的所有操作系統?

代碼取自上述答案並修改為通過窗口句柄 (hwnd) 計算窗口控制按鈕的總寬度,並將編組從 Rectangle 更改為 RECT (然后我得到正確的左/右值)。

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 ,這 3 個按鈕的組合寬度在 Windows 10 上應為 185 像素,DPI 為 125%。 請注意,如果您的應用程序不支持 DPI,那么結果仍然相同,例如 185。

[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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM