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

Java 如何仅获取窗口的可见部分(Windows、gdi32、user32等),java,windows,gdi,visible,winapi,Java,Windows,Gdi,Visible,Winapi,我只想在窗口中获取窗口的可见部分,作为一个区域 希望仅获取用户看到的区域。 当然是以编程方式。这里有一个例子。我有以下窗口组成: +------------------------------------------+ | | | +=============+ | | | | | |

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

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

+------------------------------------------+
 |                                          |
 |           +=============+                |
 |           |             |                |
 |           |    A   +--------------------------+
 |           |        |                          |
 |    C      |        |             B            |
 |           |        +--------------------------+
 |           |             |                |
 +-----------|             |----------------+
             |             |
             +-------------+
假设我只对A窗口感兴趣。 那么我需要的是一个区域的句柄,它看起来像这样:

          +=============+                
          |             |                
          |    A  +-----+
          |       |                          
          |       |                         
          |       +-----+
          |             |                
          |             |
          |             |
          +-------------+
或者,我应该能够通过以下方式获得任何其他窗口的区域

到目前为止,我使用了以下指南:

我同意GetClipBox返回0、1、2或3,如果相应地有0->Error,1表示NULLREGION(生成的rgn对用户不可见),2->SIMPLEREGION,3表示COMPLEXREGION。到目前为止,我需要这个复杂的区域

主要问题:但如何获取其坐标和尺寸

(新增信息)

是否有可能将一个复杂区域(由操作系统创建,而不是由我创建)重建为它所组成的简单区域。冯元建议你不能:

(新增信息)

那么,有没有一种方法可以找到a的区域,并将其转换为一个多边形路径或一个具有角点坐标的漂亮几何图形

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


干杯。

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

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

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

在高DPI系统上,如果Windows在应用程序中“隐藏”坐标,则您还需要小心,除非您特意将其标记为DPI感知


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

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

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

忘了提到,为了兼容性问题,我想避免使用DWM。我知道桌面窗口管理器的问题是什么,它对程序员来说太好了,但是我还想介绍XP框和禁用DWM的框;如果启用了DWM,您需要担心的一系列问题(如果您想在XP之外支持DWM等),那么一些代码可能会更好,甚至可以保证它可以完成,因为我开始怀疑在XP设备或不运行DWM的机器上是否可能。只需调用EnumWindows()枚举所有顶级窗口。它们将按深度顺序进行枚举,这样在窗口之前得到的任何数据都将位于窗口顶部,如果它们重叠,则会使窗口变得模糊。然后调用EnumDisplayMonitors()获取系统上所有监视器的矩形,以测试窗口是否实际位于屏幕上。这两个API都可以在XP上工作,也可以不使用DWM。我不知道你是从哪里知道我的建议需要DWM的。如果我调用EnumWindows,我确实可以按Z顺序对所有窗口进行排序。然而,对于那些z阶比我高的人,我不知道他们是否有重叠部分。我可以检查他们是否有。如果有人这样做了,那怎么办:)我无法得到这些区域的交点。我的问题是如何创建一个具有该区域形状和大小的复杂图形。因为我对一个地区无能为力。