我想找到桌面上给定点下面的所有顶级窗口(桌面的孩子).我找不到这个API.
我的情况是我在屏幕上拖动一个窗口,并希望将其放入另一个(已知)窗口.我可以测试目标窗口的边界确定,但这并不能告诉我它是否被另一个(未知)窗口遮挡.使用WindowFromPoint和朋友将无法工作,因为被拖动的窗口必须直接在鼠标下.所以我想知道我是否可以在鼠标位置获取所有窗口,并查看它们以查看我正在跟踪的其中一个窗口是否正在我正在拖动的窗口下方.
有没有办法在每次鼠标拖动时不依靠EnumDesktopWindows / GetWindowRect来做到这一点?或许还有另一种我不知道的解决方案.
如果你善意地询问,WindowFromPoint将忽略你的窗口(当前被拖动的窗口)并返回下一个窗口.这是Internet Explorer在拖动选项卡时执行的操作.
要做到这一点:
>在拖动的窗口中处理WM_NCHITTEST
>在拖动过程中返回HTTRANSPARENT.否则调用默认窗口proc.
> WindowFromPoint will ignore HTTRANSPARENT窗口,但只有那些属于调用线程的窗口.这应该不是一个问题,因为你应该从窗口所有者线程调用WindowFromPoint.
>确保传递给WindowFromPoint的点没有子窗口,或者也为这些子窗口处理WM_NCHITTEST.
故障排除(如果您仍然从WindowFromPoint获取窗口)
>测试GetCurrentThreadID()== GetWindowThreadProcessId(WindowFromPoint(),0)以确保从正确的线程调用
>在WM_NCHITTEST中,测试hwnd参数等于从WindowFromPoint()获得的值
示例(矩形内的区域从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,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); }