Find all windows below the dot

I want to find all the top-level windows (children of the desktop) under a specific point on the desktop. I can not find the API for this.

My scenario is that I drag a window around the screen and want to drop it into another (known) window. I can check the borders of the target window in order, but this does not tell me if it is closed by another (unknown) window. Using WindowFromPoint and friends will not work, because dragging and dropping a window is mandatory directly under the mouse. Therefore, I am wondering if I can get all the windows in the mouse position and view them to see if one of the windows that I am tracking is directly below the window that I am dragging.

Is there a way to do this without resorting to EnumDesktopWindows / GetWindowRect with every drag and drop? Or maybe there is another solution that I am missing.

+8
windows winapi
source share
2 answers

If you kindly ask, WindowFromPoint will ignore your window (which is being dragged) and return the next window. This is what Internet Explorer does when you drag a tab.

To do this:

Troubleshooting (if you still get your window from WindowFromPoint )

  • Test GetCurrentThreadID() == GetWindowThreadProcessId(WindowFromPoint(), 0) to make sure that you are calling the correct thread.
  • In WM_NCHITTEST , verify that the hwnd parameter is equal to what you get from WindowFromPoint()

Example (the area inside the rectangle returns the base window from WindowFromPoint ):

 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static const RECT s_TransparentRect = {100, 100, 200, 200}; switch (message) { case WM_NCCREATE: SetTimer(hWnd, 1, 100, 0); break; case WM_TIMER: { POINT cursorPos; GetCursorPos(&cursorPos); TCHAR buffer[256]; _snwprintf_s(buffer, _countof(buffer), _TRUNCATE, _T("WindowFromPoint: %08X\n"), (int)WindowFromPoint(cursorPos)); SetWindowText(hWnd, buffer); } break; case WM_PAINT: { PAINTSTRUCT ps; BeginPaint(hWnd, &ps); Rectangle(ps.hdc, s_TransparentRect.left, s_TransparentRect.top, s_TransparentRect.right, s_TransparentRect.bottom); EndPaint(hWnd, &ps); } break; case WM_NCHITTEST: { POINT cursorPos; GetCursorPos(&cursorPos); MapWindowPoints(HWND_DESKTOP, hWnd, &cursorPos, 1); if (PtInRect(&s_TransparentRect, cursorPos)) return HTTRANSPARENT; } break; } return DefWindowProc(hWnd, message, wParam, lParam); } 
+4
source share

That's right, you already know that WindowFromPoint () will return, there must be the one you are dragging. Then use GetWindow () with uCmd = GW_HWNDNEXT to get lower under Z-order. GetWindowRect () to get its borders, IntersectRect () to calculate the overlap.

Keep calling GetWindow () to find more windows that might overlap. Until it returns NULL, or the overlap is good enough. If not, then you usually prefer the one that has the largest result rectangle from IntersectRect ().

+3
source share

All Articles