I'm trying DwmGetWindowAttribute to get a window's real, physical, pixel location on screen. It works well for top-level windows. But I find that it does not work for child windows, in which case it returns just E_HANDLE (0x80070006).
However, MSDN does not state anything about such child-window limitation. So I'm in baffle.
Can any one confirm this behavior? Thank you.
This is my C++ test code (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;
}
This is its output:
The benefit of DwmGetWindowAttribute is: Whatever the setting of DPI_AWARENESS_CONTEXT on the calling thread, DwmGetWindowAttribute always reports physical screen coordinate. On the other hand, GetWindowRect just reports the "virtual" coordinates relating to calling thread's DPI-awareness-context. So, I am wondering whether I can use DwmGetWindowAttribute to get each top-level window and child window's physical coordinates.
