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

时间:2011-08-04 18:07:51

标签: c# .net windows winapi transparency

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

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

这对我有用的简单方法是:

  1. 暂时隐藏我的表单(或者,暂时将表单的不透明度设置为0.0)
  2. 致电[GetCursorPos] [1]
  3. 致电[WindowFromPoint] [2]
  4. 再次展示我的表格
  5. 这种方法的问题是我的表格/屏幕闪烁,我不喜欢。

    我试图通过两种方式解决这个问题:

    • 我认为应该有办法通过调用ChildWindowFromPointEx(传入桌面的hWnd和CWP_SKIPTRANSPARENT)直接在窗体下面获取窗口的hWnd,但它似乎不起作用。我还玩[ChildWindowFromPoint] [4]和[RealChildWindowFromPoint] [5]但没有成功。 (P.S. Raymond Chen讨论了这些调用之间的差异here,在我看来,ChildWindowFromPointEx的设计完全符合我的要求。

    • 我尝试在隐藏表单之前使用(1)SendMessage(GetDesktopWindow(), WM_SETREDRAW, false, 0)以及(2)SendMessage(GetDesktopWindow(), WM_SETREDRAW, true, 0)之后使用{1}}来防止整个桌面刷新(暂时“冻结”屏幕)隐藏我的表格。这样做不太正常:屏幕的某些区域会冻结,会出现一些奇怪的黑色块等等。但我知道(1)确实有效,因为有一次我打电话给(1)但没有call(2)和我的桌面看起来完全冻结(不得不重新启动,甚至TaskMgr也无法正确渲染)。我也尝试在我的表单上使用SuspendLayout和ResumeLayout,但我认为它们不是为了处理我的情况。

    非常感谢任何帮助。

1 个答案:

答案 0 :(得分:5)

您可以自己进行检查,因为您需要自定义超出标准功能所提供的内容。

  1. 致电EnumWindows()以获取顶级窗口列表。
  2. 从此列表中删除半透明窗口。
  3. 对于列表中的每个窗口,使用PtInRegion()确定鼠标是否在窗口上方。删除任何不符合账单的窗户。
  4. 使用GetNextWindow(),从剩下的一个窗口开始,走z-order,找出哪个候选者位于顶部。