我的考虑是只有Z-order在指定窗口之前的窗口才可能造成遮挡,又由于子窗口不会显示超出顶级窗口(top-level)的范围,所以只要检查Z-order在指定窗口之前的可见顶级窗口是否造成遮挡就行了。另一方面,指定窗口可能是顶级窗口或者子窗口。1、如果是顶级窗口就检查在它之前的顶级窗口;2、如果是子窗口还需要检查在它之前的子兄弟窗口是否遮挡,然后向上检查父窗口的兄弟窗口(父窗口不用检查),如此迭代直到顶级窗口为止,之后和情况1一样。还有我理解是顶级窗口和子窗口的区别在于顶级窗口没有WS_CHILD(WS_CHILDWINDOW等同)风格测试了一下似乎没什么问题,但只检查窗口矩形(Rect)是否被遮挡,没有进一步用区域(RGN)做细致比较,也没有考虑透明窗口代码如下,请大家看看有什么问题没有:bool IsCoveredByOtherWindow(HWND hWnd)
{
RECT rcTarget;
GetWindowRect(hWnd, &rcTarget); bool isChild = (WS_CHILD == (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)); do
{
HWND hCurWnd = hWnd; while ( NULL != (hWnd = GetNextWindow(hWnd, GW_HWNDPREV) ) )
{
if ( IsWindowVisible(hWnd) )
{
RECT rcWnd;
GetWindowRect(hWnd, &rcWnd); if ( !((rcWnd.right < rcTarget.left) || (rcWnd.left > rcTarget.right) ||
(rcWnd.bottom < rcTarget.top) || (rcWnd.top > rcTarget.bottom)) )
{
return true;
}
}
} if ( isChild )
{
hWnd = GetParent(hCurWnd);
isChild = hWnd ? (WS_CHILD == (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)) : false;
}
else
{
break;
} }while ( true ); return false;
}
好像可以通过FOCUS来判断是否焦点在当前窗体.
bool IsCoveredByOtherWindow(HWND hWnd)
{
RECT rcTarget;
GetWindowRect(hWnd, &rcTarget); bool isChild = (WS_CHILD == (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD));
if ( GetDesktopWindow() == hWnd ) <- 添加的代码
hWnd = GetWindow(GetTopWindow(hWnd), GW_HWNDLAST); <-
do
{
HWND hCurWnd = hWnd; while ( NULL != (hWnd = GetNextWindow(hWnd, GW_HWNDPREV) ) )
{
if ( IsWindowVisible(hWnd) )
{
RECT rcWnd;
GetWindowRect(hWnd, &rcWnd); if ( !((rcWnd.right < rcTarget.left) || (rcWnd.left > rcTarget.right) ||
(rcWnd.bottom < rcTarget.top) || (rcWnd.top > rcTarget.bottom)) )
{
return true;
}
}
} if ( isChild )
{
hWnd = GetParent(hCurWnd);
isChild = hWnd ? (WS_CHILD == (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)) : false;
}
else
{
break;
} }while ( true ); return false;
}
SetWindowPos(NULL, 99, -30, 0, 0, SWP_NOSIZE);
仍然判断没有遮挡,
估计是以为只有拖动标题栏才能移动窗口吧,
我以为判断遮挡有如下几种情况:区域(Region,包括了一般的矩形窗口)、分层窗口(Layered Window)、用绘制下层窗口的方式模拟透明效果,另外还可能需要考虑消息穿透和直接绘屏(桌面上画或者DirectX)。
遮挡到底是仅仅视觉可见,还是可见可输入,还是通过透明窗口可见但不能获得输入,或者通过透明窗口可见而且可以获得输入,透明度阀值是多少,这要根据应用场景来定义了。有部分是不能简单判断出的,比如模拟透明,还有直接绘屏(如果你的窗口背景色和后面播放器的底色一样,那你的程序就可以放电影了-_-b)。这段代码还有个bug,刚才发现的。对于子窗口的检查有两种特殊情况,就是Z-order排在上面却不挡住下面的窗口,比如分组框(GroupBox),代码里当子窗口看到有个上铺的兄弟GroupBox罩着他,就以为别人看不到自己了,回头跟我们说:“not covered!”另一种是下面挡住上面,比如两个按钮重叠在一起,你会发现Z-order在上面的按钮反而被遮挡了,但是点击重叠区点到的确实是上面的按钮!这是系统绘制子窗口顺序的问题,当上面的窗口指定WS_EX_TRANSPARENT风格时它被最后绘制,不会被挡到,但是如果再加一个WS_EX_TRANSPARENT风格的窗口重叠呢?改改用到MDI判断视图是否完全可见还是可以的,否则处理太麻烦了。能力有限,只能期待高人指教了哇