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;
}
精彩评论