C++ WinAPI 后台窗口截图

2023-12-26

我想截取没有焦点的窗口的屏幕截图。我的功能适用于某些窗口,但不适用于所有窗口,我不知道为什么。我尝试用它来捕获 Bluestacks App Player 的窗口,效果非常好。但对于 Nox App Player 和其他一些游戏来说,它根本不起作用。我只是得到一个与窗口大小相同的黑色图像。

这是到目前为止的代码:

void screenshot_window(HWND handle) {
    RECT client_rect = { 0 };
    GetClientRect(handle, &client_rect);
    int width = client_rect.right - client_rect.left;
    int height = client_rect.bottom - client_rect.top;


    HDC hdcScreen = GetDC(handle);
    HDC hdc = CreateCompatibleDC(hdcScreen);
    HBITMAP hbmp = CreateCompatibleBitmap(hdcScreen, width, height);
    SelectObject(hdc, hbmp);

    BitBlt(hdc, 0, 0, width, height, hdcScreen, 0, 0, SRCCOPY);

    BITMAPINFO bmp_info = { 0 };
    bmp_info.bmiHeader.biSize = sizeof(bmp_info.bmiHeader);
    bmp_info.bmiHeader.biWidth = width;
    bmp_info.bmiHeader.biHeight = height;
    bmp_info.bmiHeader.biPlanes = 1;
    bmp_info.bmiHeader.biBitCount = 24;
    bmp_info.bmiHeader.biCompression = BI_RGB;

    int bmp_padding = (width * 3) % 4;
    if (bmp_padding != 0) bmp_padding = 4 - bmp_padding;

    BYTE *bmp_pixels = new BYTE[(width * 3 + bmp_padding) * height];;
    GetDIBits(hdc, hbmp, 0, height, bmp_pixels, &bmp_info, DIB_RGB_COLORS);

    BITMAPFILEHEADER bmfHeader;
    HANDLE bmp_file_handle = CreateFile("TestFile.bmp", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    // Add the size of the headers to the size of the bitmap to get the total file size
    DWORD dwSizeofDIB = (width * 3 + bmp_padding) * height + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

    //Offset to where the actual bitmap bits start.
    bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);

    //Size of the file
    bmfHeader.bfSize = dwSizeofDIB;

    //bfType must always be BM for Bitmaps
    bmfHeader.bfType = 0x4D42; //BM

    DWORD dwBytesWritten = 0;
    WriteFile(bmp_file_handle, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
    WriteFile(bmp_file_handle, (LPSTR)&bmp_info.bmiHeader, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
    WriteFile(bmp_file_handle, (LPSTR)bmp_pixels, (width * 3 + bmp_padding) * height, &dwBytesWritten, NULL);

    //Close the handle for the file that was created
    CloseHandle(bmp_file_handle);

    DeleteDC(hdc);
    DeleteObject(hbmp);
    ReleaseDC(NULL, hdcScreen);
    delete[] bmp_pixels;
}

这种情况可能发生在许多应用程序中,其中目标窗口只是一个容器,不负责绘制消息。标准 win32 应用程序(如记事本)的行为并非如此。但例如,您可能会在使用许多浏览器时遇到此问题。

您始终可以截取桌面窗口的屏幕截图。您可以获取目标窗口的屏幕坐标,然后bitblt目标窗口的该部分。对您的代码进行以下更改:

//GetClientRect(handle, &client_rect);
GetWindowRect(handle, &client_rect);

//HDC hdcScreen = GetDC(handle);
HDC hdcScreen = GetDC(HWND_DESKTOP);

//BitBlt(hdc, 0, 0, width, height, hdcScreen, 0, 0, SRCCOPY);
BitBlt(hdc, 0, 0, width, height, hdcScreen, client_rect.left, client_rect.top, SRCCOPY);

//ReleaseDC(NULL, hdcScreen);
ReleaseDC(HWND_DESKTOP, hdcScreen);

在进行屏幕截图之前,目标窗口必须是屏幕上最顶层的可见窗口。例如你可以打电话screenshot_window按此顺序:

HWND hwnd = FindWindow(0, L"Calculator");
SetForegroundWindow(hwnd);
Sleep(1000);
screenshot_window(hwnd);

或者,您可以使用Dwm 缩略图 https://msdn.microsoft.com/en-us/library/windows/desktop/aa969541(v=vs.85).aspx用于在您自己的窗口中绘制目标窗口的 API。但同样,你不能使用GetDC(my_hWnd)从窗口上的“Dwm Thumbnail”访问位图。同样,您必须使用以下命令截取桌面窗口的屏幕截图GetDC(HWND_DESKTOP)。这次确保您自己的窗口是顶部窗口。

应用程序必须支持 DPI,否则屏幕坐标将不匹配。


原始代码中还存在资源泄漏。GetDC应清理ReleaseDC使用相同的handle, not NULL

HDC hdcScreen = GetDC(handle);
...
//ReleaseDC(NULL, hdcScreen);
ReleaseDC(handle, hdcScreen);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ WinAPI 后台窗口截图 的相关文章

  • 尝试了解使用服务打开对话框

    我已经阅读了有关使用 mvvm 模式打开对话框的讨论 我看过几个使用服务的示例 但我不明白所有部分如何组合在一起 我发布这个问题寻求指导 以了解我应该阅读哪些内容 以更好地理解我所缺少的内容 我将在下面发布我所拥有的内容 它确实有效 但从我
  • 转换 const void*

    我有一个函数返回一个const void 我想用它的信息作为char 我可以将它投射为 C 风格的罚款 char variable但是当我尝试使用reinterpret cast like reinterpret cast
  • MVC3中设置下拉列表中的所选项目

    我必须为视图中的下拉列表设置所选项目 但它不起作用 View div class editor label Html LabelFor model gt model Gender div div class editor field Htm
  • 未找到 Boost 库,但编译正常

    我正在尝试在 C 中使用 boost 的文件系统 使用时看起来编译没问题 c c Analyse c o Analyse o g W Wall L usr local lib lboost filesystem lboost system
  • 处理右值时的 insert 与 emplace

    std string myString std unordered set
  • 即使没有异步,CallContext.LogicalGetData 也会恢复。为什么?

    我注意到CallContext LogicalSetData LogicalGetData不按照我期望的方式工作 内部设置的值async方法得到恢复即使没有异步或任何类型的线程切换 无论如何 这是一个简单的例子 using System u
  • 如何使用 Regex.Replace 从字符串中删除数字?

    我需要使用Regex Replace从字符串中删除所有数字和符号 输入示例 123 abcd33输出示例 abcd 请尝试以下操作 var output Regex Replace input d string Empty The d标识符
  • 从网页运行 ClickOnce 应用程序,无需用户操作

    我们有一个基于 Java 的 Web 应用程序以及用 C 编写的相同应用程序 如果 java 检查器发现客户端计算机上没有安装 Java 则应该运行该应用程序 这个想法是运行 C 单击一次 http en wikipedia org wik
  • 已发布的 .Net Core 应用程序警告安装 .Net Core,但它已安装

    我制作了一个 WPF 和控制台应用程序 供某人在我无法访问的私人服务器上使用 我使用 Visual Studio 2019 的内置 发布向导 来创建依赖于框架的单文件应用程序 当该人打开 WPF 应用程序时 他们会看到标准警告 他们单击 是
  • 从 C# 使用 Odbc 调用 Oracle 包函数

    我在 Oracle 包中定义了一个函数 CREATE OR REPLACE PACKAGE BODY TESTUSER TESTPKG as FUNCTION testfunc n IN NUMBER RETURN NUMBER as be
  • 获取Windows下新线程/删除线程的通知

    创建 DLL 时 您可以在 DllMain 函数 DLL THREAD ATTACH DLL THREAD DETACH 中获取有关新线程 退出线程的通知 有没有办法在 非托管 可执行文件中从 Windows 获取这些或等效通知 是的 在您
  • 模板外部链接?谁能解释一下吗?

    模板名称具有链接 3 5 非成员函数模板可以有内部链接 任何其他模板名称应具有外部链接 从具有内部链接的模板生成的实体与在其他翻译单元中生成的所有实体不同 我知道使用关键字的外部链接 extern C EX extern C templat
  • 在 C# 中为父窗体中的子窗体控件添加事件处理程序

    我有两种形式 一种是带有按钮和文本框的父表单 单击该按钮时 将打开一个对话框 该子窗体又包含一个文本框和一个按钮 现在我想要的是 每当子表单文本框中的文本更改时 父表单文本框中的文本会自动更改 为了获得这个 我所做的是 Form3 f3 n
  • C++ - 多维数组

    处理多维数组时 是否可以为数组分配两种不同的变量类型 例如你有数组int example i j 有可能吗i and j是两种完全不同的变量类型 例如 int 和 string 听起来您正在寻找 std vector
  • 如何最好地以编程方式将 `__attribute__ ((unused))` 应用于这些自动生成的对象?

    In my makefile我有以下目标 它将文本 HTML 资源 编译 为unsigned char数组使用xxd i http linuxcommand org man pages xxd1 html 我将结果包装在匿名命名空间和标头保
  • 比较:接口方法、虚方法、抽象方法

    它们各自的优点和缺点是什么 接口方法 虚拟方法 抽象方法 什么时候应该选择什么 做出这一决定时应牢记哪些要点 虚拟和抽象几乎是一样的 虚方法在基类中有一个实现 可以选择重写 而抽象方法则没有 并且must在子类中被覆盖 否则它们是相同的 在
  • 如何解压 msgpack 文件?

    我正在将 msgpack 编码的数据写入文件 在编写时 我只是使用 C API 的 fbuffer 如 我为示例删除了所有错误处理 FILE fp fopen filename ab msgpack packer pk msgpack pa
  • WPF DataGrid / ListView 绑定到数组 mvvm

    我们假设你有 N 个整数的数组 表示行数的整数值 在模型中 该整数绑定到视图中的 ComboBox Q1 如何将数组 或数组的各个项目 绑定到 DataGrid 或 ListView 控件 以便 当您更改 ComboBox 值时 只有那么多
  • Visual Studio 2015 - Web 项目上缺少共享项目参考选项卡

    我从 MSDN 订阅升级到 Visual Studio 2015 因为我非常兴奋地阅读有关共享项目的信息 当我们想要做的只是重用代码时 不再需要在依赖项中管理 21382 个 nuget 包 所以我构建了一个测试共享项目 其中包含一些代码
  • EntityFramework 6.0.0.0 读取数据,但不插入

    我创建了一个基于服务的数据库 folderName gt Add New Item gt Data gt Service based Database文件到 WPF 应用程序中 然后我用过Database First方法并创建了Person

随机推荐

  • Javascript / jQuery 粘性,不使用 css 位置:固定

    我正在寻找一个用于粘性标题的 Javascript jQuery 插件 它不会将元素的样式切换到固定位置 通常 我正在使用这个http stickyjs com http stickyjs com 而且效果很好 我正在开发一个带有 jQ u
  • 如何忽略大文件并推送到 git repo

    之前我本地使用的是git 没有使用 gitignore然后 我创建了一个 gitignore文件 并将所有不需要的文件写入其中 当我将它们推送到 git repo 时 出现 fatal The Remote endhanged Outsta
  • 如何将一个 DataFrame 列转换为包含基于另一个 DataFrame 的列的真值表?

    我有一个df with a user id and a category 我想将其转换为真值表 以确定该用户是否至少有一个该类别的条目 但是 最终表还应包括 df list 中出现的所有类别的列 这些列可能根本不会出现在df 现在我用一个创
  • 在javascript中求10的幂,还有比这更好的方法吗

    我需要创建一个特定幂的整数值 这不是正确的术语 但基本上我需要创建 10 100 1000 等 幂 将被指定为函数参数 我想出了一个解决方案 但它感觉很老套而且错误 我想学习一种更好的方法 如果有一种方法 也许不是基于字符串的方法 此外 e
  • javascript退出for循环而不返回

    我有一个 for 循环 我想像这样退出 function MyFunction for var i 0 i lt SomeCondition i if i SomeOtherCondition Do some work here retur
  • 如何在palm mojo中使用jquery?

    我该如何才能在我的 palm mojo 应用程序中使用 jquery 查看这个问题 https stackoverflow com questions 1545773 palm pre frameworks 尤其是评论 编辑回应评论 我对P
  • 是否可以匹配React Router 4中路由的#部分

    在我的应用程序中 我想将路径和哈希与不同的组件相匹配 例如 pageA modalB 将显示 PageA 作为主页 模态 B 位于顶部 我尝试了以下方法 其中包含路径属性的许多变体
  • 无法从 Listvew.Resources 内部访问视图模型属性

    我正在尝试将 SelectedItem 绑定到视图 但是当视图位于资源块内时 视图无法访问视图模型 当数据上下文重新分配给子级时 绑定适用于文本块 但不适用于用户控件 NoteView 我是否缺少任何绑定 PFB 修改了 整个 代码和内联注
  • 衡量 React Native 应用程序的性能

    我需要测量 React Native 应用程序的性能 最好的工具是什么 我在谷歌浏览器中尝试了谷歌跟踪 并在 iOS 平台的 mac 中尝试了 Instruments 但这些显示了很多无组织的数据 我实现了一些工具来帮助我检查应用程序的性能
  • jQuery.parent() 似乎不起作用

    parent 不返回我指定的父元素 我没有发现我的代码或 html 有任何问题 JavaScript var vehicle function return init function var that this jQuery vehicl
  • Facebook 营销 API。地理搜索

    我正在尝试从 Facebook 获取一个国家 地区所有城市的列表 我从 v2 9 的 FB 文档开始 Facebook 营销 API https developers facebook com docs marketing api targ
  • 从 Windows 批处理文件将空白行回显到控制台 [重复]

    这个问题在这里已经有答案了 当从 Windows 批处理文件将状态消息输出到控制台时 我想输出空行分解输出 我该怎么做呢 以下三个选项中的任何一个都适合您 echo echo echo 例如 echo off echo There will
  • 在 Heroku 上安装 PyODBC 时找不到 sql.h

    我正在尝试在 Heroku 上安装 PyODBC 但我得到fatal error sql h No such file or directorypip 运行时的日志中 我该如何修复这个错误 要跟进下面的答案 Ubuntu 的示例 sudo
  • Azure Functions RunOnStartUp 在配置中设置而不是在编译时设置?

    我有一个 Azure 计时器触发函数 计划在生产中每 3 个月运行一次 然而 在测试环境中 我希望它在每次触发时在启动时运行 目前我有 TimerTrigger TimerInterval RunOnStartup false 我真的不想改
  • 使用 dplyr 和 rollapply 在数据框中滚动预测

    我的第一个问题在这里 我的目标是 给定一个带有预测变量的数据框 每列一个预测变量 行观察值 使用 lm 拟合回归 然后使用滚动窗口使用最后一个观察值来预测值 数据框如下所示 gt DfPredictor 1 40 Y X1 X2 X3 X4
  • 为什么人们一致推荐使用 appConfig 而不是使用设置文件? (。网)

    我经常看到这样的问题的答案 我应该如何在我的 NET 应用程序中存储设置 是通过手动向 app config 或 web config 添加条目来编辑 app config 文件 如下所示
  • 参数“ContactsCtrl”不是函数,未定义

    我在 AngularJS 路由和控制器中遇到问题 这是代码 索引 html div div index js var myApp angular module contacts
  • 水豚服务器和浏览器错误,服务器上没有任何痕迹

    由于某种原因 我的黄瓜测试之一似乎在 poltergeist 驱动程序和 Rails 服务器上都失败了 我得到了浏览器崩溃的完整跟踪信息 但服务器端几乎没有任何信息 当我打开水豚屏幕截图时 我只看到 内部服务器错误 未定义的方法name对于
  • 如何在ckeditor5中的`a`标签中添加“target”属性?

    我已经创建了自己的链接插件 现在我想添加一些其他属性a插件生成的标签 例如target rel 但我无法完成它 这是我的转换器插件代码 我应该添加哪些转换器以便a标签可以支持其他属性吗 license Copyright c 2003 20
  • C++ WinAPI 后台窗口截图

    我想截取没有焦点的窗口的屏幕截图 我的功能适用于某些窗口 但不适用于所有窗口 我不知道为什么 我尝试用它来捕获 Bluestacks App Player 的窗口 效果非常好 但对于 Nox App Player 和其他一些游戏来说 它根本