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

yar*_*one 3 .net c# windows winapi transparency

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

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

对我来说,这样做的简单方法是:

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

这种方法的问题是我的表格/屏幕闪烁,我不喜欢.

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

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

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

任何帮助将不胜感激.

Dav*_*nan 5

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

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