开发者

How to get only the visible part of a window (Windows, gdi32, user32, etc)

I want to get only the visible part of the window in windows, as a region.

Want to get only the area that is seen by the user. Programmatically, of course. Here is an example. I have the following window composition:

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

Let's say that I am interested only in window A. Then what I would need is a handle to a region which would look like this:

          +=============+              开发者_JAVA百科  
          |             |                
          |    A  +-----+
          |       |                          
          |       |                         
          |       +-----+
          |             |                
          |             |
          |             |
          +-------------+

Alternatively, I should be able to obtain the region of any other window in the following manner.

So far, I used this guide, and I agree that GetClipBox returns 0, 1, 2 or 3 if you have, accordingly, 0 -> Error, 1 for NULLREGION(the resulting rgn is invisible to the user), 2 -> SIMPLEREGION, and 3 for COMPLEXREGION. So, far, I need the complex region.

Master Question: But how do I get its coordinates and dimensions ?

(Added Info)

Is it possible to reconstruct a COMPLEXREGION (That was created by the OS, not me) to simple REGIONS of which it is composed. Feng Yuan suggests you can't:

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

(Added Info)

So, is there a way to find the region of A and translate it to a PolyPath or a nice geometric figure having the coordinates of its corners ?

I use JNA (Java) , by the way, but a C# or .VB code solving the same problem would be sufficient.

Cheers.


You can enumerate all desktop windows, plus all monitors, and combine their rectangles. I'm not sure if there is a better way.

Note that Windows "lies" about the exact dimensions of windows these days (the Aero window border is slightly bigger than actually reported unless you set a special flag).

Also note that windows can have see-through portions defined by each application (in addition to the see-through window borders you always have under Aero).

You also need to be careful on high-DPI systems where Windows "lies" to your app about coordinates unless you go out of your way to flag it as DPI-aware.

And also note that even an "invisible" window can be visible via the Taskbar, Alt-Tab or Flip3D thumbnails feature of Aero... So, really, on Vista and Windows 7 with DWM enabled, the answer is that your window is potentially always completely visible. :)


I have written a small function which computes the visible region of any window. Pass window handle to this function and It will return visible region of the window.

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜