获取鼠标指针下的窗口句柄,同时忽略半透明窗口

本文关键字:透明窗口 鼠标指针 窗口句柄 获取 | 更新日期: 2023-09-27 18:04:27

我创建了一个半透明的窗体(60%不透明度,黑色背景色),我的应用程序启动,最大化,在整个屏幕上。基本上,它在整个桌面上投射出灰色。

当用户鼠标移到桌面上的窗口上时,我想获得该窗口的句柄(hWnd)。

最简单的方法是:

  1. 暂时隐藏我的窗体(或者,暂时设置我的窗体的不透明度为0.0)
  2. 调用[GetCursorPos] [1]
  3. 调用[WindowFromPoint] [2]
  4. 再次显示我的表单

这个方法的问题是我的表单/屏幕会闪烁,这是我不喜欢的。

我试过用两种方法来解决这个问题:

  • 我想应该有一种方法可以通过调用ChildWindowFromPointEx(在桌面和CWP_SKIPTRANSPARENT的hWnd中传递)直接在我的表单下面获得窗口的hWnd,但它似乎不起作用。我也玩了[ChildWindowFromPoint][4]和[RealChildWindowFromPoint][5]没有成功。(P.S. Raymond Chen讨论了这些调用之间的差异,在这里,在我看来,ChildWindowFromPointEx的设计正是为了做我需要的)

  • 我试图防止整个桌面刷新(一种"冻结"屏幕暂时)使用(1)SendMessage(GetDesktopWindow(), WM_SETREDRAW, false, 0)之前,我隐藏我的形式和(2)SendMessage(GetDesktopWindow(), WM_SETREDRAW, true, 0)后,我隐藏我的形式。这并不能很好地工作:屏幕的某些区域会冻结,一些奇怪的黑色块会出现,等等。然而,我确实知道(1)是有效的,因为有一次我调用了(1)而没有调用(2),我的桌面看起来完全冻结了(不得不重新启动,甚至TaskMgr都不能正确渲染)。我也试过在我的表单上使用SuspendLayout和ResumeLayout,但我不认为它们是为了处理我的情况。

获取鼠标指针下的窗口句柄,同时忽略半透明窗口

您可以自己检查,因为您需要自定义超出标准函数提供的功能。

  1. 调用EnumWindows()获取顶级窗口列表
  2. 从列表中删除半透明窗口
  3. 对于列表中的每个窗口,使用PtInRegion()来确定鼠标是否在窗口上方。删除所有不合适的窗口。
  4. 使用GetNextWindow(),从剩下的一个窗口开始走z顺序,找出哪个候选在顶部。