惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
G
Google Developers Blog
J
Java Code Geeks
爱范儿
爱范儿
Microsoft Azure Blog
Microsoft Azure Blog
美团技术团队
人人都是产品经理
人人都是产品经理
Martin Fowler
Martin Fowler
IT之家
IT之家
博客园_首页
B
Blog RSS Feed
Google DeepMind News
Google DeepMind News
B
Blog
U
Unit 42
Apple Machine Learning Research
Apple Machine Learning Research
L
LangChain Blog
Stack Overflow Blog
Stack Overflow Blog
罗磊的独立博客
N
Netflix TechBlog - Medium
T
Tailwind CSS Blog
博客园 - 聂微东
腾讯CDC
A
About on SuperTechFans

博客园 - StationaryTraveller

如何查找微软VS软件中的图标 SQLite 的自增(AUTOINCREMENT)强制要求列的数据类型必须是INTEGER Qt动态获取翻译文本 MFC实现一个通用模态进度条窗口 如何批量修改“后期生成事件”为“预生成事件” MFC对话框中如何给一个控件发送消息 Window剪切板 C语言根据函数指针偏移实现函数动态调用 Qt程序系统文本翻译 SVN创建分支 Qt多版本如何共存 Qt6编译的程序在某些win10系统报错 电脑忘机了用户名密码怎么办 Qt事件过滤器实现空闲检测 CMFCToolTipCtrl的AddTool导致内存增加 MFC中CBitmap、CBrush、CFont、CPalette、CPen、CRgn删除GDI对象问题 实现从QListWidgett拖拽项到QTableWidget Windows系统下通过命令行获取进程指标 命令模式实现撤销和重做机制 避免溢出求平均值的算法 字节流转16进制字符串 PImpl:Pointer to Implementation C++单例
Windows判断某窗口是否被其他窗口完全覆盖
StationaryTr · 2026-03-12 · via 博客园 - StationaryTraveller
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宏包围的代码全部删除。