6

我只想在窗口中获取窗口的可见部分,作为一个区域。

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

+------------------------------------------+
 |                                          |
 |           +=============+                |
 |           |             |                |
 |           |    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 代码就足够了。

干杯。

4

2 回答 2

4

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

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

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

在高 DPI 系统上,您还需要小心 Windows 在坐标方面对您的应用“撒谎”,除非您特意将其标记为可识别 DPI。

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

于 2010-11-16T17:47:30.767 回答
1

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

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;
}
于 2012-12-14T05:25:01.100 回答