确定Vista中的窗口可见性

时间:2008-11-05 07:04:13

标签: winapi windows-vista

我想确定某个窗口是对用户可见还是隐藏/遮挡。在Windows XP中,我将使用GetClipBox()函数并检查NULLREGION或空RECT返回值。这工作得很好,但在Windows Vista上,如果另一个窗口遮挡了窗口,它就无法工作。在这种情况下,GetClipBox()返回带有非空RECT的SIMPLEREGION。

有人知道为什么这不适用于Vista,或者是否有其他方法可以检查用户是否可以看到某个窗口?

5 个答案:

答案 0 :(得分:2)

在安装Vista时,是否打开了桌面窗口管理器组合?我猜它是,如果你把它关闭,你会得到预期的XP行为。问题是在Vista下使用DWM组合,处理窗口的方式发生了很大变化,我认为没有一种简单的方法可以达到你想要的效果。

答案 1 :(得分:2)

GetClipBox()在启用DWM时未返回NULLREGION的简单原因是因为您没有被剪裁! DWM的整个点是每个窗口(不是孩子,如按钮或编辑框)获取它自己的缓冲区来绘制,因此前景窗口可以移动而不必填充它们后面的窗口。

举个简单的例子,当它在后台时,将鼠标悬停在任务栏中的窗口条目上,并在预览中看到它正在更新。

另请注意,对于玻璃边缘,您的窗户可以被其他窗户完全覆盖,并且仍然可见! (你甚至无法测试客户区,因为扩展的玻璃,就像Windows Media Player使用的那样 - 将它调整到尽可能小的尺寸并看到它在整个区域使用玻璃!)当然,分层窗口(从XP开始) )和自定义窗口区域意味着总是这样,但现在它是默认值。

<强>概要/ TL; DR:

如果您正在进行繁重的动画/花哨效果并希望在DWM下运行时减少CPU使用率,那么您可以做的最好的事情就是检测应用程序何时失去前景并回退到更加CPU友好的更新(不是没有更新!如果你得到一个WM_PAINT,并忽略它,因为你在后台,当你被激活时你不会得到它!)。

答案 2 :(得分:1)

这样做有点混乱的方法是获取要检查的窗口的位置/大小,然后遍历所有窗口高于Z顺序的窗口并计算它们覆盖的窗口的哪些部分

答案 3 :(得分:1)

  

在您的Vista安装中,是桌面版   窗口管理器组成打开?   我猜它是,如果   你把它关掉你会得到的   预期的XP行为。问题是   在具有DWM组成的Vista下,   窗户的处理方式有   改变很多,我不认为   有一个简单的方法可以实现   你想要什么。

是的,我的机器上启用了DWM。我尝试了以下测试你的假设:

  1. 右键单击我的应用程序并选择“属性”
  2. 点击“兼容性”标签
  3. 启用“禁用桌面合成”复选框
  4. 点击“应用”
  5. 此后,GetClipBox()函数正常工作。所以你的预感是正确的。我发现我可以通过在我的应用程序中使用以下函数以编程方式执行此操作:

    DwmEnableComposition(DWM_EC_DISABLECOMPOSITION);
    

    但是,这会在我的应用程序运行时禁用透明效果,这是不可取的。我宁愿不那么突兀的解决方案。

    无论如何,感谢您的建议!

答案 4 :(得分:0)

由于您知道GetClipRect的输出在XP和Vista上(启用和不启用DWM),您可以创建一个函数来确定它根据操作系统采用不同的路径。在伪代码中:

function bool IsWindowVisible()
{
   bool isVisible = false;

   if (OSVersion == "XP")
   {
      // GetClipRect tests which run on XP and set isVisible
   }
   else if (OSVersion == "Vista")
   {
      if (DWMCompisitionEnabled == true)
      {
         // GetClipRect tests for Vista with DWM enabled and set isVisible
      }
      else
      {
         // GetClipRect tests for Vista with DWM disabled and set isVisible
      }
   }
   return isVisible;
}