查找一个点下的所有窗口 [英] Find all windows beneath a point

查看:21
本文介绍了查找一个点下的所有窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在桌面上的给定点下找到所有顶级窗口(桌面的子窗口).我找不到这方面的 API.

I want to find all the top-level windows (children of the desktop) beneath a given point on the desktop. I can't find an API for this.

我的情况是我在屏幕上拖动一个窗口并希望将其放入另一个(已知)窗口中.我可以点击测试目标窗口的边界,但这并不能告诉我它是否被另一个(未知)窗口遮挡.使用 WindowFromPoint 和朋友是行不通的,因为被拖动的窗口必须直接在鼠标下方.所以我想知道我是否可以在鼠标位置获取所有窗口,并查看它们以查看我正在跟踪的窗口之一是否直接位于我正在拖动的窗口下方.

My scenario is that I'm dragging a window across the screen and want to drop it into another (known) window. I can hit test the bounds of the target window ok, but that doesn't tell me whether it's occluded by another (unknown) window. Using WindowFromPoint and friends won't work, because the window being dragged is necessarily directly under the mouse. So I'm wondering if I can obtain all windows at the mouse position, and review them to see whether one of the windows I'm tracking is directly beneath the window I'm dragging.

有没有办法在每次鼠标拖动时不诉诸 EnumDesktopWindows/GetWindowRect 的情况下做到这一点?或者也许我缺少另一个解决方案.

Is there a way to do this without resorting to EnumDesktopWindows/GetWindowRect on every mouse drag? Or perhaps there's another solution I'm missing.

推荐答案

如果您善意地询问,WindowFromPoint 将忽略您的窗口(当前正在拖动的窗口)并返回下一个窗口.这就是 Internet Explorer 在您拖动选项卡时所做的事情.

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

要做到这一点:

  1. 处理被拖动窗口中的WM_NCHITTEST
  2. 在拖动过程中返回 HTTRANSPARENT.否则调用默认窗口过程.
  3. WindowFromPoint 将忽略HTTRANSPARENT 窗口,但仅限于那些属于调用线程的窗口.这对您来说应该不是问题,因为无论如何您都应该从窗口所有者线程调用 WindowFromPoint.
  4. 确保在传递给 WindowFromPoint 的点上没有子窗口,或者也为这些子窗口处理 WM_NCHITTEST.
  1. Handle WM_NCHITTEST in window being dragged
  2. Return HTTRANSPARENT during dragging. Call default window proc otherwise.
  3. WindowFromPoint will ignore HTTRANSPARENT windows, but only those belonging to the calling thread. This shouldn't be a problem for you, because you should be calling WindowFromPoint from the window owner thread anyway.
  4. Make sure there're no child windows at point passed to WindowFromPoint, or handle WM_NCHITTEST for these child windows as well.

疑难解答(如果您仍然从 WindowFromPoint 获取窗口)

Troubleshooting (if you still get your window from WindowFromPoint)

  1. 测试 GetCurrentThreadID() == GetWindowThreadProcessId(WindowFromPoint(), 0) 以确保您从正确的线程调用
  2. WM_NCHITTEST 中,测试 hwnd 参数是否等于您从 WindowFromPoint() 获得的参数
  1. Test GetCurrentThreadID() == GetWindowThreadProcessId(WindowFromPoint(), 0) to ensure you're calling from correct thread
  2. In WM_NCHITTEST, test that hwnd parameter equals what you get from WindowFromPoint()

示例(矩形内的区域从WindowFromPoint返回底层窗口):

Example (the area within rectangle returns the underlying 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);
}

这篇关于查找一个点下的所有窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆