首页 > 解决方案 > DwmGetWindowAttribute 对子窗口不起作用,是真的吗?

问题描述

我正在尝试DwmGetWindowAttribute在屏幕上获取窗口的真实、物理、像素位置。它适用于顶级窗口。但我发现它不适用于子窗口,在这种情况下它只返回E_HANDLE0x80070006)。

但是,MSDN没有说明这种子窗口限制。所以我很困惑。

任何人都可以确认这种行为吗?谢谢你。

这是我的 C++ 测试代码(DwmBounds.cpp):

#include <stdio.h>
#include <windows.h>
#include <dwmapi.h>

int main()
{
    DWORD winerr = 0;
    HWND hwndTop = FindWindow(L"Notepad", NULL);
    if(!hwndTop)
    {
        wprintf(L"Cannot find a Notepad window.\n");
        return 4;
    }

    RECT rc = {};
    HRESULT hr = DwmGetWindowAttribute(hwndTop, DWMWA_EXTENDED_FRAME_BOUNDS, &rc, sizeof(rc));
    if (hr != S_OK)
    {
        wprintf(L"Fail to call DwmGetWindowAttribute() on Notepad window. HRESULT=0x%08X\r\n",
            (DWORD)hr);
        return 4;
    }

    wprintf(L"Notepad DWMWA_EXTENDED_FRAME_BOUNDS: LT(%d, %d) RB(%d, %d)\r\n", 
        rc.left, rc.top, rc.right, rc.bottom);

    HWND hwndEdit = FindWindowEx(hwndTop, nullptr, L"Edit", nullptr);
    if (!hwndEdit)
        return 4;

    hr = DwmGetWindowAttribute(hwndEdit, DWMWA_EXTENDED_FRAME_BOUNDS, &rc, sizeof(rc));
    if(hr != S_OK)
    {
        // Always get HRESULT=0x80070006 (E_HANDLE), why?
        wprintf(L"Get DWMWA_EXTENDED_FRAME_BOUNDS fails on child window(0x%08X), HRESULT=0x%08X\n", 
            (DWORD)hwndEdit, (DWORD)hr);
        return 4;
    }

    wprintf(L"Editbox DWMWA_EXTENDED_FRAME_BOUNDS: LT(%d, %d) RB(%d, %d)\r\n",
        rc.left, rc.top, rc.right, rc.bottom);

    return 0;
}

这是它的输出:

在此处输入图像描述

这样做的好处DwmGetWindowAttribute是:无论DPI_AWARENESS_CONTEXT调用线程上的设置如何,DwmGetWindowAttribute总是报告物理屏幕坐标。另一方面,GetWindowRect只报告与调用​​线程的 DPI-awareness-context 相关的“虚拟”坐标。所以,我想知道我是否可以DwmGetWindowAttribute用来获取每个顶级窗口和子窗口的物理坐标。

标签: dwm

解决方案


推荐阅读