Tip 72 : How do I determine if the user can see my window?
The answer to this one depends upon whether you wish to determine if the user
can see your whole window, part of your window, or a specific point on your
window.
A Single Point
to determine if the user can see a
specific point, you can find the screen coordinates of that point, call
WindowFromPoint, and check to see if the handle returned from WindowFromPoint is
the same as yours. If so, you'd think the user can see that point (though of
course it could be one pixel peeping out from behind the multiple windows
covering it up). This simple function should test if the user can see the middle
of your window :
BOOL IsWindowCentreVisibleToUser (HWND hWnd)
{
BOOL bRetVal = FALSE;
RECT rcWnd;
POINT pt;
if (IsWindow
(hWnd))
{
GetWindowRect (hWnd, &rcWnd);
pt.x = rcWnd.left + (rcWnd.right - rcWnd.left)/2;
pt.y = rcWnd.top + (rcWnd.bottom - rcWnd.top)/2;
bRetVal = (WindowFromPoint (pt) == hWnd);
}
return bRetVal;
}
BUT - the down side of this simplistic solution is that
WindowFromPoint doesn't return handles for disabled windows. Ack... so we need
something better. Read on...
The Window, Whole or Part
Things get a little more complicated when we're talking about all or part of a
window. Basically, the trick is to make the system do the work for you by using
the clipping system. Take a look at the code below:
#define IWVTU_FULL
1
#define IWVTU_PARTIAL 2
#define IWVTU_HIDDEN 3
#define IWVTU_ERROR 4
UINT IsWindowVisibleToUser (HWND hWnd)
{
UINT uRetVal = IWVTU_ERROR;
int
iClipRes;
HDC hdcWnd;
RECT rcWndClient;
RECT rcWndClip;
if (IsWindow (hWnd))
{
// This uses the clipping
system to determine if the user
// can see
all or part of the window. The only problem
// comes when the region returned is a rectangle,
i.e. the
// return code from GetClipBox is SIMPLEREGION.
In that
// case we check against the client area
rectangle, on the
// basis that what we _really_ care about is the
contents
// of the window, not the caption bar.
hdcWnd = GetDC (hWnd);
GetClientRect (hWnd, &rcWndClient);
iClipRes = GetClipBox (hdcWnd, &rcWndClip);
ReleaseDC (hWnd, hdcWnd);
switch
(iClipRes)
{
case
NULLREGION:
uRetVal = IWVTU_HIDDEN;
break;
case
SIMPLEREGION:
if
(EqualRect (&rcWndClip, &rcWndClient))
uRetVal = IWVTU_FULL;
else
uRetVal = IWVTU_PARTIAL;
break;
case
COMPLEXREGION:
uRetVal = IWVTU_PARTIAL;
break;
default:
uRetVal = IWVTU_ERROR;
break;
}
}
return
uRetVal;
}
This latter sample is based upon an idea originally posted by Russ
Freeman.