【问题标题】:How to get only the visible part of a window (Windows, gdi32, user32, etc)如何仅获取窗口的可见部分(Windows、gdi32、user32 等)
【发布时间】:2011-05-10 21:31:04
【问题描述】:

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

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

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

干杯。

【问题讨论】:

    标签: java windows gdi visible winapi


    【解决方案1】:

    您可以枚举所有桌面窗口以及所有监视器,并组合它们的矩形。不知道有没有更好的办法。

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

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

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

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

    【讨论】:

    • 忘了说,为了兼容性问题,我想避免使用 DWM。我知道桌面窗口管理器有什么问题,它对程序员来说太棒了,但是我还想介绍 XP 框和禁用 DWM 的框。
    • 我并不是建议您将 DWM 用于任何事情;只是指出启用 DWM 时您必须担心的一堆问题(如果您想在 XP 等之外支持它)
    • 好吧,一些代码会更好,甚至可以保证它可以完成,因为我开始怀疑它是否可能在 XP 机器或不运行 DWM 的机器上。
    • 只需调用 EnumWindows (msdn.microsoft.com/en-us/library/ms633497%28VS.85%29.aspx) 即可枚举所有顶级窗口。它们将按深度顺序进行枚举,因此您在窗口之前获得的任何内容都将位于其顶部,并且如果它们重叠将使其模糊。然后调用 EnumDisplayMonitors (msdn.microsoft.com/en-us/library/dd162610%28VS.85%29.aspx) 以获取系统上所有监视器的矩形,以测试您的窗口实际上是否在屏幕上。这两个 API 都可以在 XP 上运行,并且没有 DWM。不知道你从哪里知道我的建议需要 DWM。
    • 如果我调用 EnumWindows,我确实可以得到所有按 Z 顺序排序的窗口。但是,对于那些z-order比我高的人,我不知道他们是否有任何重叠部分。我实际上可以检查他们是否这样做。如果有人这样做,那么:) 我无法获得这些地区的交集。我的问题是如何创建一个具有区域形状和大小的复杂图形。因为我不能对区域做任何事情。
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-15
      • 2021-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-08
      • 1970-01-01
      相关资源
      最近更新 更多