2010-11-16 70 views
3

我想仅获取窗口中窗口的可见部分作为区域。如何仅获取窗口的可见部分(Windows,gdi32,user32等)

只想获得用户看到的区域。当然,以编程方式编写代码 。这是一个例子。我有以下窗口组成:

+------------------------------------------+ 
|           | 
|   +=============+    | 
|   |    |    | 
|   | A +--------------------------+ 
|   |  |       | 
| C  |  |    B   | 
|   |  +--------------------------+ 
|   |    |    | 
+-----------|    |----------------+ 
      |    | 
      +-------------+ 

比方说,我感兴趣的只是窗口A. 那我会需要的是一个句柄区域,该区域是这样的:

  +=============+     
      |    |     
      | A +-----+ 
      |  |       
      |  |       
      |  +-----+ 
      |    |     
      |    | 
      |    | 
      +-------------+ 

或者,我应该能够以下面的方式获得任何其他窗口的区域。

到目前为止,我用这个指南: http://blogs.msdn.com/b/oldnewthing/archive/2003/09/02/54758.aspx

我同意GetClipBox返回0,1,2或3,如果你有,因此,0 - >错误,1 NULLREGION(所得RGN是用户不可见),2 - > SIMPLEREGION,3用于COMPLEXREGION。所以,我需要复杂的地区。

主要问题:但是,如何获得其坐标和尺寸

(添加信息)

是否有可能重建COMPLEXREGION(这是由操作系统创建的,不是我),以简单的地区,其中它是由。冯远建议您不能:

http://www.codeguru.com/forum/archive/index.php/t-126543.html

(添加信息)

那么,有没有办法找到A的区域和将其转换为POLYPATH或一个不错的几何具有其角落坐标的图形

顺便说一下,我使用JNA(Java),但解决相同问题的C#或.VB代码就足够了。

干杯。

回答

2

您可以枚举所有桌面窗口以及所有显示器并组合它们的矩形。我不确定是否有更好的方法。

请注意,Windows对这些天窗口的确切尺寸“存在”(除非您设置特殊标志,否则Aero窗口边框比实际报告稍大)。

另请注意,Windows可以有每个应用程序定义的透视部分(除了透视窗口边框,您总是在Aero下)。

您还需要注意高DPI系统,Windows对您的应用程序进行坐标关于坐标,除非您想方设法将其标记为支持DPI。

还要注意,即使是“隐形”窗口也可以通过Aero的任务栏,Alt-Tab或Flip3D缩略图功能看到。所以,实际上,在启用了DWM的Vista和Windows 7上,答案是您的窗口可能始终完全可见。 :)

+0

忘了提及,我想避免使用DWM,兼容性问题。我知道桌面窗口管理器存在什么问题,对于程序员来说非常棒,但是我也想要覆盖XP盒子以及禁用DWM的盒子。 – 2010-11-16 22:29:37

+0

我并不是建议你为任何东西使用DWM;只是指出了一堆问题,如果启用了DWM(如果您希望在XP等之外支持它),那么您必须担心一些问题。 – 2010-11-16 23:17:59

+0

那么一些代码会更好,或者甚至可以保证它可以完成,因为我开始怀疑它可能在XP机器或不运行DWM的机器上。 – 2010-11-17 08:19:03

0

我写了一个小函数,它计算任何窗口的可见区域。 将窗口句柄传递给此函数,它将返回窗口的可见区域。

HRGN GetVisibleRegion(HWND hwnd) 
{ 
    //Store the region of window hwnd 
    RECT hwndRect={0,0,0,0}; 
    ::GetWindowRect(hwnd,&hwndRect); 
    HRGN rgn=::CreateRectRgn(hwndRect.left,hwndRect.top,hwndRect.right,hwndRect.bottom); 


    //HWND hParentWnd=::GetParent(hwnd); 
    HWND hParentWnd=::GetAncestor(hwnd,GA_PARENT); 
    HWND hChildWnd=hwnd; 
    //until we reaches desktop window 
    while(hChildWnd!=NULL && hChildWnd!=GetDesktopWindow()) 
    { 
     HWND topWnd=::GetTopWindow(hParentWnd); 
     do 
     { 
      if(topWnd==hChildWnd) 
      { 
       break; 
      } 
      RECT topWndRect={0,0,0,0}; ::GetWindowRect(topWnd,&topWndRect); 
      RECT tempRect={0,0,0,0}; 
      //Other window overlapping with hwnd 
      if(::IsWindowVisible(topWnd) && !::IsIconic(topWnd) && IntersectRect(&tempRect,&topWndRect,&hwndRect)!=0) 
      { 
       HRGN topWndRgn=::CreateRectRgn(topWndRect.left,topWndRect.top,topWndRect.right,topWndRect.bottom); 
       ::CombineRgn(rgn,rgn,topWndRgn,RGN_DIFF); 
       ::RealDeleteObject(topWndRgn); 
      } 
      topWnd = GetNextWindow(topWnd, TWO); 

     }while(topWnd!=NULL); 
     hChildWnd=hParentWnd; 
     //hParentWnd=::GetParent(hParentWnd); 
     hParentWnd=::GetAncestor(hParentWnd,GA_PARENT); 
    } 
    return rgn; 
}