隐藏窗口的PrintWindow和BitBlt [英] PrintWindow and BitBlt of hidden windows

查看:667
本文介绍了隐藏窗口的PrintWindow和BitBlt的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的程序正在拍摄其他应用程序窗口的屏幕快照,以自动执行它们上的某些任务.这些窗口可能会隐藏在屏幕外,或者不时被其他窗口遮盖.

My program is taking screenshots of other application windows to automate some tasks on them. Those windows can be hidden offscreen or obscured by other windows from time to time.

为了减少混乱,我从代码清单中删除了所有错误检查.我正在准备两种类型的屏幕截图

To reduce clutter, I have removed any error checking from the code listings. I am preparing the both types of screenshots with

// 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);

然后我要使用其中一个来获取实际的屏幕截图

then I am taking the actual screenshots with either

PrintWindow(hwnd, memoryDC, PW_CLIENTONLY); 
GdiFlush();

UpdateWindow(hwnd);
BitBlt(memoryDC, 0, 0, width, height, windowDC, 0, 0, SRCCOPY);
GdiFlush();

然后将缓冲区内容复制到向量

then I copy the buffer contents to a vector

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);

关于上述代码,我有三个问题:

I have a three of questions about the code above:

  1. 我需要打GdiFlush()吗?我阅读了文档并进行了一些Google研究,但仍不确定是否可以调用它.
  2. BitBlt()之前对UpdateWindow()的调用会有所不同吗?这是否有帮助,以使设备上下文"的内容更及时"?
  3. 我正确地认为,对于PrintWindow(),所有工作都在目标应用程序内完成(增加了目标应用程序的CPU使用率),而BitBlt()在调用线程内完全执行了(因此增加了CPU使用率)我自己的应用程序)?
  4. 在哪种情况下上述任何功能可能会失败?我知道BitBlt()仅在启用桌面合成(DWM)的情况下才适用于隐藏的窗口,但是在极少数系统(Windows 8/10)上,BitBlt()PrintWindow()似乎对于适用于它们的窗口失败在其他系统上也没问题(即使启用了DWM).不过,我无法发现任何原因.
  1. Do I need to call GdiFlush()? I read the documentation and did some Google research, but I am still not sure if it makes sense to call it or not.
  2. Does the call to UpdateWindow() right before the BitBlt() make a difference? Does this help, so that the Device Context contents are "more up to date"?
  3. Am I right in assuming that for PrintWindow() all the work is done from within the target application (increasing the target application's CPU usage), while BitBlt() is fully executed from within the calling thread (thus increasing the CPU usage of my own application)?
  4. Under which circumstances might any of the above functions fail? I know that BitBlt() only works for hidden windows if Desktop Composition (DWM) is enabled, but on a very small set of systems (Windows 8/10) BitBlt() and PrintWindow() seem to fail for windows for which they work just fine on other systems (even though DWM is enabled). I could not spot any patterns as to why, though.

感谢您提供任何信息.

推荐答案

最后,经过几个小时的调查,我找到了解决该问题的方法: 在要成像的表单的ACTIVATE事件中调用以下命令就足够了(以VB编码为例):

finally, after some hours of investigation, I found a solution for that issue: It's sufficient to call the following command within the ACTIVATE event of the form to be imaged (example in VB coding):

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

Best regards, Bambi66

这篇关于隐藏窗口的PrintWindow和BitBlt的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆