代码之家  ›  专栏  ›  技术社区  ›  Nikola Yovchev

如何只获取窗口的可见部分(Windows、gdi32、user32等)

  •  4
  • Nikola Yovchev  · 技术社区  · 14 年前

    我只想得到窗口的可见部分,作为一个区域。

    只想得到用户看到的区域。 当然是程序化的。这是一个例子。我有以下窗户组成:

    +------------------------------------------+
     |                                          |
     |           +=============+                |
     |           |             |                |
     |           |    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(由操作系统创建,而不是由me创建)重构为其组成的简单区域。冯媛建议你不能:

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

    (添加信息)

    那么,有没有办法找到 将其转换为具有角坐标的多路径或漂亮的几何图形 ?

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

    干杯。

    2 回复  |  直到 14 年前
        1
  •  2
  •   Leo Davidson    14 年前

    您可以枚举所有桌面窗口,加上所有监视器,并组合它们的矩形。我不确定是否有更好的方法。

    请注意,Windows“撒谎”的确切尺寸的窗口这些天(空气动力学窗口边框略大于实际报告,除非你设置了一个特殊的标志)。

    还要注意,windows可以有由每个应用程序定义的透明部分(除了Aero下始终具有的透明窗口边框)。

    在高DPI系统上,你也需要小心,因为Windows会在应用程序中“隐藏”坐标,除非你特意将其标记为DPI感知。

    还要注意,即使是“不可见”窗口也可以通过Aero的任务栏、Alt选项卡或Flip3D缩略图功能看到。。。因此,实际上,在启用了DWM的Vista和Windows 7上,答案是您的窗口可能总是完全可见的。:)

        2
  •  1
  •   Sipka    10 年前

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

    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;
    }