Windows判断某窗口是否被其他窗口完全覆盖
bool IsCompletelyCovered(HWND hWnd)
{
// 1. 基本有效性检查
if (!IsWindow(hWnd))
return true;
// 2. 如果窗口不可见或最小化,认为被覆盖
if (!IsWindowVisible(hWnd) || IsIconic(hWnd))
return true;
// 3. 获取窗口矩形
RECT rect;
if (!GetWindowRect(hWnd, &rect))
return true;
LONG width = rect.right - rect.left;
LONG height = rect.bottom - rect.top;
if (width <= 0 || height <= 0)
return true;
// 4. 定义采样点(13个)
POINT points[] = {
{ rect.left, rect.top }, // 左上
{ rect.right - 1, rect.top }, // 右上
{ rect.left, rect.bottom - 1 }, // 左下
{ rect.right - 1, rect.bottom - 1 }, // 右下
{ rect.left + width / 2, rect.top }, // 上中
{ rect.left + width / 2, rect.bottom - 1 }, // 下中
{ rect.left, rect.top + height / 2 }, // 左中
{ rect.right - 1, rect.top + height / 2 }, // 右中
{ rect.left + width / 2, rect.top + height / 2 }, // 中心
{ rect.left + width / 4, rect.top + height / 4 }, // 左上区域中心
{ rect.left + 3 * width / 4, rect.top + height / 4 }, // 右上区域中心
{ rect.left + width / 4, rect.top + 3 * height / 4 }, // 左下区域中心
{ rect.left + 3 * width / 4, rect.top + 3 * height / 4 } // 右下区域中心
};
#ifdef _DEBUG
std::set<HWND> coveringWindows; // 用于去重保存遮挡窗口句柄
#endif // _DEBUG
// 5. 检查每个采样点
for (const auto& pt : points)
{
HWND hWndAtPt = WindowFromPoint(pt);
// 如果获取失败,视为该点不可达(可能被系统级窗口覆盖)
if (hWndAtPt == NULL)
{
continue;
}
// 如果点所在窗口是目标窗口本身或其子窗口,则属于目标窗口区域
if ((hWndAtPt == hWnd) || IsChild(hWnd, hWndAtPt))
{
return false;
}
#ifdef _DEBUG
coveringWindows.insert(hWndAtPt);
#endif // _DEBUG
}
#ifdef _DEBUG
// 所有采样点都被其他窗口覆盖
if (!coveringWindows.empty())
{
//输出目标窗口信息
TCHAR targetTitle[256] = { 0 };
TCHAR targetClass[256] = { 0 };
GetWindowText(hWnd, targetTitle, _countof(targetTitle));
GetClassName(hWnd, targetClass, _countof(targetClass));
TCHAR wndBuf[1024] = { 0 };
LOG(INFO) << u8"------------------------------------------------------";
_stprintf_s(wndBuf, _T("目标窗口:句柄=\"0x%p\",标题=\"%s\",类名=\"%s\""), hWnd, targetTitle, targetClass);
LOG(INFO) << wndBuf;
LOG(INFO) << u8"遮挡窗口个数:" << coveringWindows.size();
int i = 1;
for (HWND hCover : coveringWindows)
{
TCHAR coverTitle[256] = { 0 };
TCHAR coverClass[256] = { 0 };
GetWindowText(hCover, coverTitle, _countof(coverTitle));
GetClassName(hCover, coverClass, _countof(coverClass));
TCHAR coverBuf[1024] = { 0 };
_stprintf_s(coverBuf, _T("遮挡窗口%d:句柄=\"0x%p\",标题=\"%s\",类名=\"%s\""), i++, hCover, coverTitle, coverClass);
LOG(INFO) << coverBuf;
}
}
#endif // _DEBUG
return true;
}
说明:
1.如果子窗口遮挡了父窗口,该方法不认为被遮挡,因为子属于父的一部分。如果不需要这样处理,可将IsChild条件去掉。
2.该函数增加了打印信息,如果不需要,可将Debug宏包围的代码全部删除。

浙公网安备 33010602011771号