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

推荐订阅源

T
Tenable Blog
Last Week in AI
Last Week in AI
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
H
Help Net Security
F
Fortinet All Blogs
MyScale Blog
MyScale Blog
宝玉的分享
宝玉的分享
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - 司徒正美
量子位
N
Netflix TechBlog - Medium
Apple Machine Learning Research
Apple Machine Learning Research
小众软件
小众软件
Recorded Future
Recorded Future
博客园 - 三生石上(FineUI控件)
Vercel News
Vercel News
aimingoo的专栏
aimingoo的专栏
I
InfoQ
Microsoft Security Blog
Microsoft Security Blog
Scott Helme
Scott Helme
The Last Watchdog
The Last Watchdog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
IT之家
IT之家
AI
AI
WordPress大学
WordPress大学
Security Archives - TechRepublic
Security Archives - TechRepublic
Google Online Security Blog
Google Online Security Blog
U
Unit 42
V2EX - 技术
V2EX - 技术
MongoDB | Blog
MongoDB | Blog
Schneier on Security
Schneier on Security
博客园 - Franky
H
Heimdal Security Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Jina AI
Jina AI
W
WeLiveSecurity
P
Privacy & Cybersecurity Law Blog
Cloudbric
Cloudbric
B
Blog RSS Feed
N
News | PayPal Newsroom
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
I
Intezer
Hacker News - Newest:
Hacker News - Newest: "LLM"
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
博客园_首页
罗磊的独立博客
H
Hackread – Cybersecurity News, Data Breaches, AI and More
雷峰网
雷峰网

博客园 - StationaryTraveller

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宏包围的代码全部删除。