捕获最小化窗口的缩略图画面

这篇具有很好参考价值的文章主要介绍了捕获最小化窗口的缩略图画面。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

关键字:

capture minimized window

window thumbnail

IsIconic 

==================== 问题背景 ======================

最小化的窗口,API GetClientRect 返回的窗口尺寸是0x0,故无法通过GetDC+BitBlt捕获到窗口画面。

但是 Agora/zoom/tencentMeeting 都可以拿到最小化窗口的缩略图。经确认这个程序并没有注入任何dll到目标窗口,且也没有临时显示最小化了的目标窗口。

如果用SHOW_RESTORE恢复最小化了的目标窗口,目标窗口是会收到WM_MOVE消息的,测试Agora/zoom/tencent抓最小化窗口的缩略图时,最小化的窗口并没有收到这个消息,事实上,目标窗口没有收到任何窗口消息。

小记:

  1. agora zoom 腾讯会议 在目标窗口最小化时, 都可以拿到窗口缩略图
  2. 拿到的该缩略图,画面和任务栏鼠标悬停时显示的缩略图一致(该缩略图并不是实时的,而是窗口最小化时刻的画面)
  3. 获取缩略图时,目标窗口没有收到任何窗口消息(SPY)
  4. 开始捕获窗口后,这几个视频会议软件 均可以恢复最小化了的窗口(即使目标窗口是管理员权限启动)

==================== 可用的方法 ====================

方法1(不推荐!)

WS_EX_LAYERED, SetLayeredWindowAttributes

方法2:

DWM接口,关键字:DwmRegisterThumbnail,DwmUpdateThumbnailProperties

通过注入Dll + hook API(DwmRegisterThumbnail)的方式验证zoom进程,发现其就是用dwm捕获最小化窗口画面的。

在zoom的窗口选择界面,所有目标窗口的画面捕获和刷新 都是用的dwm,zoom每次调用dwmRegister 传入的dest HWND都是同一个句柄,且刚刚就是窗口选择界面的顶层窗口句柄,

目标窗口最小化和restore期间,zoom没有调用过dwmUnregister,应该是调用了dwmUpdate(尚未验证)。

方法3:

WGC接口,关键字:GraphicsCapturePicker.PickSingleItemAsync (是系统提供的子进程界面)

GitHub - robmikh/Win32CaptureSample: A simple sample using the Windows.Graphics.Capture APIs in a Win32 application.

================ DWM接口 ========================

关键字:

DWM(桌面窗口管理器)API , 可以实现获取目标窗口的缩略图(即使目标窗口是最小化)

DWM API应用之缩略图_老狼主的博客-CSDN博客_c++ dwm api

DWM API应用之缩略图 - CodeAntenna

Windows 使用 DuiLib 显示屏幕和窗口缩略图_12194415的技术博客_51CTO博客

DwmRegisterThumbnail function (dwmapi.h) - Win32 apps | Microsoft Learn

DwmUpdateThumbnailProperties function (dwmapi.h) - Win32 apps | Microsoft Learn

DwmUnregisterThumbnail function (dwmapi.h) - Win32 apps | Microsoft Learn

注意:

1. 一旦用DwmRegisterThumbnail和DwmUpdateThumbnail,绑定了缩略图关系后,只要不调用DwmUnregister,源窗口的画面就会被系统持续自动更新到目标窗口,不需要手动去刷新画面。

2. 一旦源窗口销毁了,目标窗口上的画面也就没有了(系统会自动清空)

3. 源窗口和目标窗口 都必须是顶层窗口,且目标窗口必须是当前进程的窗口

4. UWP窗口的源窗口句柄,需要设置为parent host句柄(EnumWindows的回调形参HWND就是parent句柄)

#include <dwmapi.h>
#pragma comment(lib,"Dwmapi.lib")

HRESULT RegisterThumbWindow(HWND hWndSrc, HWND hWndDst)
{
    HTHUMBNAIL thumbnail = NULL;
    HRESULT hr = DwmRegisterThumbnail(hWndDst, hWndSrc, &thumbnail);
        if (FAILED(hr))
        return hr; // 如果窗口句柄不存在 或传入了非顶层窗口的句柄 此处会出错

    RECT dest;
        GetClientRect(hWndDst, &dest);

    DWM_THUMBNAIL_PROPERTIES dskThumbProps;
    dskThumbProps.dwFlags = DWM_TNP_RECTDESTINATION | DWM_TNP_VISIBLE | DWM_TNP_SOURCECLIENTAREAONLY |DWM_TNP_OPACITY; // 标识哪些字段已经设置了有效值
    dskThumbProps.fSourceClientAreaOnly = FALSE;
    dskThumbProps.fVisible = TRUE;
    dskThumbProps.rcDestination = dest;
    dskThumbProps.opacity = 255;

    hr = DwmUpdateThumbnailProperties(thumbnail, &dskThumbProps);
        if (FAILED(hr))
        OutputDebugStringA("error");

        // DwmUnregisterThumbnail(thumbnail);
        return hr;
}

void CMFCApplication4Dlg::OnBnClickedButton1()
{
        // 要把缩略图显示在这个窗口 注意:根据MSDN这个窗口必须是顶层窗口,否则返回错误E_INVALIDARG
        // 注意 这个句柄 必须是【当前进程】的窗口句柄
    HWND hwndDestination = m_hWnd; 
    
        // 想捕获的源窗口 这个句柄也必须是顶层窗口句柄,UWP窗口在此处需要设置为parent host句柄
        HWND hwndSource = (HWND)0X004E0286; 
       
        RegisterThumbWindow(hwndSource, hwndDestination);
}

===================== WGC接口 =====================

GitHub - walker-WSH/Win32CaptureSample: A simple sample using the Windows.Graphics.Capture APIs in a Win32 application.

这个项目,点击按钮“Open Picker”, 会弹出一个窗口 用来显示所有窗口 包含最小化窗口的缩略图。

但是这个弹出窗口是系统的,主程序退出后 这个窗口都还在。如果捕获窗口利用的是WGC技术,则可以完全复用系统的这个picker窗口。

捕获最小化窗口的缩略图画面

这个弹出的子窗口,实际上是系统提供的独立进程:

捕获最小化窗口的缩略图画面

================= WS_EX_LAYERED ===================

技术点:临时把窗口显示出来(SW_RESTORE),捕获到一帧窗口画面后,再把窗口恢复最小化。

显示窗口之前,需要做如下准备:

1. 给目标窗口增加扩展属性 WS_EX_LAYERED(增加了这个属性 才可以设置窗口透明度)。

2. 用API设置窗口的透明度为透明 (让用户感知不到窗口被显示了)SetLayeredWindowAttributes / GetLayeredWindowAttributes。

3. 临时关闭系统的最大化和最小化的动画效果 animation(否则临时restore最小化的窗口时 系统有动画效果 被用户感知)。

恢复了最小化的窗口 抓取到窗口画面后,再恢复以上几个属性(有些窗口可能之前就有透明度,要注意保存以前的值)

注意:

以上操作,如果是UWP窗口,需要设置的HWND对象是外层的host窗口。

TODO:

尚未验证过如果目标窗口是管理员权限进程的,如下API设置layered透明度是否还能成功?

HWND hWnd = 0;
    if (pTemp->pObject->bIsUWP) {
        hWnd = pTemp->pObject->hParent; // 如果是UWP窗口 需要使用host窗口
    } else {
        hWnd = pTemp->pObject->hActual;
    }

    if (IsWindow(hWnd)) {
        if (IsIconic(hWnd)) {
            ModifyStyleEx2(hWnd, 0, WS_EX_LAYERED); // 增加了这个属性 才可以设置半透明
            SetLayeredWindowAttributes(hWnd, 0, 155, LWA_ALPHA); // 设置整个窗口透明
                        // TODO: 临时关闭系统的最大化和最小化的动画效果
            ShowWindow(hWnd, SW_RESTORE);                        // 显示窗口

            // TODO: capture window video

            // TODO: 移除layered属性,恢复最小化状态。
            // 注意:需要确认之前是否有layer属性,以及对应透明度。GetLayeredWindowAttributes
            ShowWindow(hWnd, SW_MINIMIZE);
        }
    }

备注:

显示最小化窗口时,如果目标窗口是管理员权限运行,而自己的进程不是,则使用ShowWindow则会收到last error = 5。此时想显示最小化的目标窗口,应该用如下两种方法之一。文章来源地址https://www.toymoban.com/news/detail-468864.html

// 方法1 
// [此功能不适用于一般用途。它可能会在后续版本的 Windows 中更改或不可用。]
// 根据微软注释 这个API不建议使用了。
SwitchToThisWindow(hWnd, TRUE) 


// 方法2 (推荐使用)
PostMessage(hWnd, WM_SYSCOMMAND, (WPARAM)SC_RESTORE, 0)

到了这里,关于捕获最小化窗口的缩略图画面的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • electron在最小化窗口后,任务栏右键关闭再托盘唤起黑屏的解决方法

    在点击托盘唤醒的回调函数下我的代码是这样的: 因为我想要最小化后再唤醒可以回到原始窗口状态,比如最大化。但是这么唤醒后会导致页面黑屏,在找了很多文档无果。最后在我试验再次调用.show后成功唤醒了 所以 ,最后我的解决方案是在restore后再次调用show方法进行展

    2024年02月11日
    浏览(57)
  • 关于Windows桌面远程后,unity程序无法全屏显示或者显示窗口默认最小化解决方法

    按以下步骤操作 1、Win+R打开运行,然后输入regedit打开注册表 2、根据计算机HKEY_CURRENT_USERSoftwareDefaultCompany路径找到DefaultCompany的文件夹 3、在DefaultCompany文件夹下找到unity打包时exe文件对应名称的文件夹,右键删除整个文件夹,删除后再去启动unity.exe程序即可恢复正常显示画

    2024年04月10日
    浏览(58)
  • 【Qt UI相关】Qt中如何控制 窗口的最大化、最小化和关闭按钮?一文带你掌握用法

    窗口的最大化、最小化和关闭按钮通常是由操作系统的窗口管理器控制的,而不是由应用程序控制的。这些按钮的行为(例如点击最大化按钮会将窗口的大小调整为屏幕的大小)是由窗口管理器实现的,应用程序通常不能改变这些行为。 在 Qt 中,你可以通过 QWidget::setWindow

    2024年02月11日
    浏览(31)
  • 机器学习的学习准则(期望风险最小化、经验风险最小化、结构风险最小化)

    训练集是有N个独立同分布的样本组成,即每个样本(x,y)是独立的从相同的分布中抽取的。这个真实的分布未知 输入空间X和输出空间Y构成样本空间,对于样本空间中的样本(x, y)∈X x Y,假定x和y之间可通过一个未知的真实隐射y=g(x)来描述,或者通过真实条件概率分布来描述。

    2024年02月09日
    浏览(37)
  • DFA的最小化

    一、实验目的 1.熟练掌握DFA与NFA的定义与有关概念。 2.理解并掌握确定的有穷自动机的最小化等算法。 二、实验要求 输入:DFA 输出:最小化的DFA 三、实验过程 1.化简DFA关键在于把它的状态集分成一些两两互不相交的子集,使得任何两个不相交的子集间的状态都是可区分

    2024年02月09日
    浏览(40)
  • QT最小化程序到托盘运行

    实现程序关闭时最小化托盘的功能 托盘实现显示主页面和退出的功能 支持扩展,直接引用TrayIcon类即可,对外暴露接口 单例实现,可复用 注:博主所有资源永久免费,若有帮助,请点赞转发是对我莫大的帮助 注:博主本人学习过程的分享,引用他人的文章皆会标注原作者

    2024年02月05日
    浏览(39)
  • LeetCode——最小化字符串长度

    目录 一、题目 二、题目解读  三、代码  1、set去重 2、用一个二进制数记录每个字母是否出现过 6462. 最小化字符串长度 - 力扣(Leetcode) 给你一个下标从  0  开始的字符串  s  ,重复执行下述操作  任意  次: 在字符串中选出一个下标  i  ,并使  c  为字符串下标  i

    2024年02月08日
    浏览(32)
  • LabVIEW开发最小化5G系统测试平台

    LabVIEW开发最小化5G系统测试平台 由于具有大量存储能力和数据的应用程序的智能手机的激增,当前一代产品被迫提高其吞吐效率。正交频分复用由于其卓越的品质,如单抽头均衡和具有成本效益的实施,现在被广泛用作物理层技术。这些好处是以严格的同步、正交性和高功耗

    2024年02月12日
    浏览(29)
  • unity发布设置(最小化、置顶、限制单开)

    1. 勾上下图标红处,发布后可防止按windows键缩小  2.发布后程序默认最小化 3.发布的程序只能开一个进程

    2024年02月12日
    浏览(33)
  • 最小化安装Linux系统初始化脚本

    目录 最小化安装Linux系统初始化脚本 注:此脚本适用于centos 7/8、Ubuntu1804,具体需要根据实际情况进行测试调整。 此脚本包含的功能: 允许 root 用户使用 ssh 登录 关闭 selinux 关闭防火墙 设置 ps1 设置默认编辑器为 vim 自定义 vim 自定义历史命令 修改内核参数 设置资源限制 修

    2024年02月12日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包