如果 MediaPlayer 处于全屏模式,DwmGetWindowAttribute 无法获得正确的 Rect 大小

DwmGetWindowAttribute doesn't get the correct Rect size for MediaPlayer if it's in full screen mode

我正在尝试使用此代码获取应用程序大小:

      [DllImport(@"dwmapi.dll")]
      private static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out Rect pvAttribute, int cbAttribute);

    [Serializable, StructLayout(LayoutKind.Sequential)]
    private struct Rect
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;

        public Rectangle ToRectangle()
        {
            return Rectangle.FromLTRB(Left, Top, Right, Bottom);
        }
    }

      private static bool DWMWA_EXTENDED_FRAME_BOUNDS(IntPtr handle, out Rectangle rectangle)
        {
        Rect rect;
        var result = DwmGetWindowAttribute(handle, (int)Dwmwindowattribute.DwmwaExtendedFrameBounds,
            out rect, Marshal.SizeOf(typeof(Rect)));
        rectangle = rect.ToRectangle();
        return result >= 0;
         }

它对所有 运行 应用程序都工作正常,但如果它是处于全屏模式的媒体播放器,我没有得到正确的矩形大小。

Windows Media Player 在全屏模式下很奇怪,因此主 window 手柄与显示的全屏 window 不对应。全屏 window 仍然有一个句柄,但需要做更多的工作才能得到它。

首先您需要声明一些 WinAPI 函数和结构:

delegate bool EnumWindowsProc(IntPtr hwnd, IntPtr lParam);

[DllImport("User32.dll")]
static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);

[DllImport("User32.dll")]
static extern bool GetMonitorInfo(IntPtr hMonitor, ref MonitorInfo lpmi);

[DllImport("User32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

[DllImport("User32.dll")]
static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags);

[StructLayout(LayoutKind.Sequential)]
struct MonitorInfo
{
    public uint Size;
    public Rect Monitor;
    public Rect Work;
    public uint Flags;
}

// You seem to have this one already
[StructLayout(LayoutKind.Sequential)]
struct Rect
{
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
}

从那里开始,方法如下所示:

// Pass Windows Media Player's main window handle here.
static bool GetWmpFullScreenHandle(IntPtr mainHandle, out IntPtr fullScreenHandle)
{
    IntPtr tempHandle = IntPtr.Zero;

    // Getting WMP's PID from the main window handle.
    GetWindowThreadProcessId(mainHandle, out uint wmpProcessId);

    // Optionally, check if the PID resolves to a WMP process.
    if (System.Diagnostics.Process.GetProcessById(wmpProcessId).ProcessName != "wmplayer")
    {
        fullScreenHandle = IntPtr.Zero;

        return false;
    }

    // This iterates through all the open window handles on the machine
    // and passes them to the callback below.
    EnumWindows((hWnd, lParam) =>
    {
        // Getting the window handle's PID.
        GetWindowThreadProcessId(hWnd, out uint windowProcessId);

        // Checking if the window handle belongs to the WMP process.
        if (windowProcessId == wmpProcessId)
        {
            var monitorInfo = new MonitorInfo
            {
                Size = Convert.ToUInt32(Marshal.SizeOf(typeof(MonitorInfo)))
            };

            // Getting the dimensions of the monitor the window is displayed on,
            // as well as the window dimensions.
            if (GetMonitorInfo(MonitorFromWindow(hWnd, 0), ref monitorInfo) && 
                GetWindowRect(hWnd, out Rect windowRect))
            {
                Rect monitorRect = monitorInfo.Monitor;

                // If the window dimensions are the same as its monitor's
                // dimensions, then we found a hidden full-screen window!
                if (windowRect.Left == monitorRect.Left &&
                    windowRect.Top == monitorRect.Top &&
                    windowRect.Right == monitorRect.Right &&
                    windowRect.Bottom == monitorRect.Bottom)
                {
                    tempHandle = hWnd;
                }
            }
        }

        return true;
    },
    IntPtr.Zero);

    fullScreenHandle = tempHandle;

    // Returns true if the hidden full-screen handle was found, false otherwise.
    return fullScreenHandle != IntPtr.Zero;
}

如果找到,您可以将结果句柄传递给 DWMWA_EXTENDED_FRAME_BOUNDS 以获取 Rectangle