查找一个点下的所有窗口 [英] Find all windows beneath a point
问题描述
我想在桌面上的给定点下找到所有顶级窗口(桌面的子窗口).我找不到这方面的 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.
要做到这一点:
- 处理被拖动窗口中的
WM_NCHITTEST
- 在拖动过程中返回
HTTRANSPARENT
.否则调用默认窗口过程. WindowFromPoint
将忽略HTTRANSPARENT
窗口,但仅限于那些属于调用线程的窗口.这对您来说应该不是问题,因为无论如何您都应该从窗口所有者线程调用WindowFromPoint
.- 确保在传递给
WindowFromPoint
的点上没有子窗口,或者也为这些子窗口处理WM_NCHITTEST
.
- Handle
WM_NCHITTEST
in window being dragged - Return
HTTRANSPARENT
during dragging. Call default window proc otherwise. WindowFromPoint
will ignoreHTTRANSPARENT
windows, but only those belonging to the calling thread. This shouldn't be a problem for you, because you should be callingWindowFromPoint
from the window owner thread anyway.- Make sure there're no child windows at point passed to
WindowFromPoint
, or handleWM_NCHITTEST
for these child windows as well.
疑难解答(如果您仍然从 WindowFromPoint
获取窗口)
Troubleshooting (if you still get your window from WindowFromPoint
)
- 测试
GetCurrentThreadID() == GetWindowThreadProcessId(WindowFromPoint(), 0)
以确保您从正确的线程调用 - 在
WM_NCHITTEST
中,测试hwnd
参数是否等于您从WindowFromPoint()
获得的参数
- Test
GetCurrentThreadID() == GetWindowThreadProcessId(WindowFromPoint(), 0)
to ensure you're calling from correct thread - In
WM_NCHITTEST
, test thathwnd
parameter equals what you get fromWindowFromPoint()
示例(矩形内的区域从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屋!