我的程序正在拍摄其他应用程序窗口的屏幕快照,以自动执行它们上的某些任务.这些窗口可能会隐藏在屏幕外或被其他窗口不时遮盖.
为了减少混乱,我从代码清单中删除了所有错误检查.我正在准备两种类型的屏幕截图
// 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()吗?我阅读了文档并做了一些Google研究,但是仍然不确定是否可以调用它.
>在BitBlt()之前对UpdateWindow()的调用会有所不同吗?这是否有帮助,以便使设备上下文的内容“更最新”?
>我是否认为对于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