c++ - 隐藏窗口的 PrintWindow 和 BitBlt
问题描述
我的程序正在截取其他应用程序窗口的屏幕截图,以自动执行一些任务。这些窗口可能会不时隐藏在屏幕外或被其他窗口遮挡。
为了减少混乱,我从代码清单中删除了所有错误检查。我正在准备两种类型的屏幕截图
// Get size of the target window.
RECT clientRect;
GetClientRect(hwnd, &clientRect);
int width = clientRect.right - clientRect.left;
int height = clientRect.bottom - clientRect.top;
// Create a memory device context.
HDC windowDC = GetDC(hwnd);
HDC memoryDC = CreateCompatibleDC(windowDC);
// Create a bitmap for rendering.
BITMAPINFO bitmapInfo;
ZeroMemory(&bitmapInfo, sizeof(BITMAPINFO));
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo.bmiHeader.biWidth = width;
bitmapInfo.bmiHeader.biHeight = -height;
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biBitCount = 32;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
bitmapInfo.bmiHeader.biSizeImage = width * height * 4;
RGBQUAD* buffer;
HBITMAP bitmap = CreateDIBSection(windowDC, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, 0, 0);
HGDIOBJ previousObject = SelectOBject(memoryDC, bitmap);
然后我会用任何一个来截取实际的截图
PrintWindow(hwnd, memoryDC, PW_CLIENTONLY);
GdiFlush();
或者
UpdateWindow(hwnd);
BitBlt(memoryDC, 0, 0, width, height, windowDC, 0, 0, SRCCOPY);
GdiFlush();
然后我将缓冲区内容复制到向量
std::vector<RGBQUAD> pixels;
pixels.resize(width * height, { 0, 0, 0, 0 });
memcpy(&pixels[0], buffer, bitmapInfo.bmiHeader.biSizeImage);
最后我正在清理一切
ReleaseDC(hwnd, windowDC);
SelectObject(memoryDC, previousObject);
DeleteDC(memoryDC);
DeleteObject(bitmap);
我对上面的代码有三个问题:
- 我需要打电话
GdiFlush()
吗?我阅读了文档并做了一些谷歌研究,但我仍然不确定调用它是否有意义。 - 调用
UpdateWindow()
正确之前的调用是否BitBlt()
有所作为?这是否有帮助,以便设备上下文内容“更新”? - 我是否正确假设
PrintWindow()
所有工作都是在目标应用程序中完成的(增加目标应用程序的 CPU 使用率),而BitBlt()
在调用线程中完全执行(从而增加我自己的应用程序的 CPU 使用率)? - 在哪些情况下,上述任何功能可能会失败?我知道
BitBlt()
只有在启用桌面组合 (DWM) 的情况下才适用于隐藏窗口,但在非常小的一组系统 (Windows 8/10)上BitBlt()
,并且PrintWindow()
对于它们在其他系统上工作得很好的窗口似乎失败了(即使 DWM已启用)。不过,我找不到任何关于为什么的模式。
任何信息表示赞赏,谢谢。
解决方案
最后,经过几个小时的调查,我找到了解决该问题的方法:在要成像的表单的 ACTIVATE 事件中调用以下命令就足够了(VB 编码中的示例):
Call SetWindowLong(me.hwnd, GWL_EXSTYLE, WS_EX_LAYERED)
而该命令定义如下:
Private Declare Function SetWindowLong Lib "User32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Const GWL_EXSTYLE = (-20)
Private Const WS_EX_LAYERED = &H80000
请试试这个!
最好的问候, Bambi66
推荐阅读
- python - 将 django 多项选择字段与文本输入连接
- reactjs - 我的元素没有相应地移动到 onPanResponderMove
- c# - WebApi 自定义 BufferedMediaTypeFormatter WriteToStream 永远不会被调用
- sql - sql(4 不同列) 中的 Dense_rank 查询
- sql - 使用 SQL 中多列的值创建列
- react-native - 如何手动链接库?
- java - 默认情况下总是在菜单切换中运行
- javascript - 为什么等待/异步的结果未定义?
- azure - 将 Azure 自定义脚本扩展从 Blob 添加到 Powershell 的虚拟机规模集
- arrays - 使用多重索引枚举多线性映射的 Swift 算法:[Int]