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

C# 获取鼠标指针下方的窗口句柄,同时忽略半透明窗口,c#,.net,windows,winapi,transparency,C#,.net,Windows,Winapi,Transparency,我已经创建了一个半透明表单(60%不透明,背景颜色为黑色),我的应用程序可以在整个屏幕上最大化地启动。基本上,它在整个桌面上投射灰色 当用户将鼠标移到桌面上的某个窗口上时,我希望获得该窗口的句柄(hWnd) 对我来说,最简单的方法是: 暂时隐藏我的窗体(或暂时将窗体的不透明度设置为0.0) 致电[GetCursorPos][1] 致电[WindowFromPoint][2] 再次出示我的表格 这种方法的问题是我的表单/屏幕会闪烁,这是我不喜欢的。 我尝试用两种方法解决这个问题: 我想应该有一种

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

当用户将鼠标移到桌面上的某个窗口上时,我希望获得该窗口的句柄(hWnd)

对我来说,最简单的方法是:

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

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

    • 我想应该有一种方法可以通过调用(传入桌面的hWnd和
      CWP\u SKIPTRANSPARENT
      )直接在我的表单下面获取窗口的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,但我认为它们不适合处理我的情况


    任何帮助都将不胜感激。

    您可以自己进行检查,因为您需要定制超出标准功能范围的功能

  • 调用
    EnumWindows()
    以获取顶级窗口的列表
  • 从此列表中删除半透明窗口
  • 对于列表中的每个窗口,使用
    PtInRegion()
    确定鼠标是否在窗口上方。移除所有不符合要求的窗户
  • 使用
    GetNextWindow()
    ,从剩余的一个窗口开始遍历z顺序,找出哪个候选项位于顶部

  • 因为我是一个新用户,不得不删除一堆有用的链接。那有点蹩脚。你是在找顶层窗口,还是需要子窗口?您希望如何处理遇到的半透明窗口?@David Heffernan是的,只查找顶级窗口(桌面的直接子窗口)。不完全确定,但EnumWindows甚至可能会枚举z顺序渲染(4)不必要。如果没有记录,那么你就不能依赖它behaviour@sertac我确实看过,但没有医生。不过我打赌你是对的。我认为获取所有顶级窗口列表的另一种方法是Process.getprocesss()。并检查.MainWindowTitle(如果它不是null或空白,我认为这意味着它是一个顶级窗口)和.MainWindowHandle