Winapi 打印窗口:屏幕截图有时会偏移
我正在使用PrintWindow()拍摄windows的屏幕截图。这与以下代码一起工作 这在大多数情况下都有效——我经常在连续循环中调用它——但有时会失败。我开始保存它失败时的屏幕截图。有时它们只是黑色的,但有时捕捉到的窗口的客户区域在某种程度上是偏移的,并且仅在图片的一半上可见。为什么会这样 编辑: PrintWindow函数是否保证能正常工作,即使每秒调用100次?让我感到奇怪的是,在每次打印窗口之后,我实际上都在验证启动时存储为COLORREF的默认颜色的两个像素。该节目说,他们几乎所有的时间都匹配。尽管如此,一旦我使用GetPixel,其他像素返回的值有时只是黑色或白色(这种情况永远不会发生)。一旦我将HDC/HBITMAP保存为一个屏幕截图(我之前称为GdiFlush),屏幕截图就是纯黑色的(正如我所说,也不应该是这种情况,我之前检查了两个像素…)。 现在,回到最初的问题:这肯定是我的错,还是PrintWindow可能只是不时给出随机结果而不返回错误 好的,这是新代码:Winapi 打印窗口:屏幕截图有时会偏移,winapi,screenshot,Winapi,Screenshot,我正在使用PrintWindow()拍摄windows的屏幕截图。这与以下代码一起工作 这在大多数情况下都有效——我经常在连续循环中调用它——但有时会失败。我开始保存它失败时的屏幕截图。有时它们只是黑色的,但有时捕捉到的窗口的客户区域在某种程度上是偏移的,并且仅在图片的一半上可见。为什么会这样 编辑: PrintWindow函数是否保证能正常工作,即使每秒调用100次?让我感到奇怪的是,在每次打印窗口之后,我实际上都在验证启动时存储为COLORREF的默认颜色的两个像素。该节目说,他们几乎所有的
/* Try printing the window 10times, in case it fails. */
for (int i = 0; i <= NUM_ITERATIONS_PREP; i++) {
releaseSurface();
prepared_HWND = hwnd;
window_dc = GetWindowDC(hwnd);
surface = CreateCompatibleDC(window_dc);
if (surface) {
RECT r;
GetWindowRect(hwnd, &r);
bmp = CreateCompatibleBitmap(window_dc, r.right - r.left, r.bottom - r.top);
if (!ReleaseDC(hwnd, window_dc)) {
writeLog("ReleaseDC failed.", black, true);
}
if (bmp) {
old_surface_bmp = SelectBitmap(surface, bmp);
//InvalidateRect(hwnd, 0, TRUE);
//UpdateWindow(hwnd);
int result = PrintWindow(hwnd, surface, 0);
if (result != 0) {
if (!verify || verifySurface())
break;
else {
writeLog("Surface could not be verified on iteration " + std::to_string(i) + ". Saving screenshot.", black, true);
saveDebugScreenshot();
QThread::msleep(2);
}
} else {
writeLog("PrintWindow() failed.", black, true);
}
}
else {
writeLog("BMP creation failed.", black, true);
}
}
else {
writeLog("HDC creation failed.", black, true);
}
}
releaseSurface()在prepareSurface()开始时调用,另外每次处理完表时调用(这意味着对每个prepareSurface()调用一次太频繁了。这有问题吗?)
Oh和old_surface_bmp、bmp和surface被声明为私有类属性。当您说“it fails”时,是指某个函数调用失败,还是只是捕获的位图不正确?只是位图不正确。只要我正确地释放HDC,函数调用就不会失败。一些GDI调用可能是异步的,所以我想当你保存位图时,它可能处于不一致的状态。请尝试调用
GdiFlush
,并确保在将位图保存到磁盘之前取消从DC中选择位图。好的,我会试试。失败是指GetPixel接收到的像素颜色完全错误(它们与保存的bmp匹配,但与屏幕上窗口的客户区域不匹配)。我感觉窗口在打印到HDC之前没有完全重新绘制,但这并没有真正意义,因为据我所知,PrintWindow()会擦除背景,在重新粉刷之前?我实现了check now,它总是将打印图像上的两个像素与预先存储的验证颜色进行比较,如果它们不匹配,则再次调用PrintWindow()。通常,这必须重复4次,直到表面最终得到验证。到目前为止,这似乎效果不错,尽管它更像是一种变通方法。
/* If you call prepareSurface(), call this once the surface isn't need anymore. */
void ClientProfile::releaseSurface() {
SelectObject(surface, old_surface_bmp);
DeleteDC(surface);
DeleteObject(bmp);
prepared_HWND = NULL;
}