Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Winapi 打印窗口:屏幕截图有时会偏移_Winapi_Screenshot - Fatal编程技术网

Winapi 打印窗口:屏幕截图有时会偏移

Winapi 打印窗口:屏幕截图有时会偏移,winapi,screenshot,Winapi,Screenshot,我正在使用PrintWindow()拍摄windows的屏幕截图。这与以下代码一起工作 这在大多数情况下都有效——我经常在连续循环中调用它——但有时会失败。我开始保存它失败时的屏幕截图。有时它们只是黑色的,但有时捕捉到的窗口的客户区域在某种程度上是偏移的,并且仅在图片的一半上可见。为什么会这样 编辑: PrintWindow函数是否保证能正常工作,即使每秒调用100次?让我感到奇怪的是,在每次打印窗口之后,我实际上都在验证启动时存储为COLORREF的默认颜色的两个像素。该节目说,他们几乎所有的

我正在使用PrintWindow()拍摄windows的屏幕截图。这与以下代码一起工作

这在大多数情况下都有效——我经常在连续循环中调用它——但有时会失败。我开始保存它失败时的屏幕截图。有时它们只是黑色的,但有时捕捉到的窗口的客户区域在某种程度上是偏移的,并且仅在图片的一半上可见。为什么会这样

编辑: PrintWindow函数是否保证能正常工作,即使每秒调用100次?让我感到奇怪的是,在每次打印窗口之后,我实际上都在验证启动时存储为COLORREF的默认颜色的两个像素。该节目说,他们几乎所有的时间都匹配。尽管如此,一旦我使用GetPixel,其他像素返回的值有时只是黑色或白色(这种情况永远不会发生)。一旦我将HDC/HBITMAP保存为一个屏幕截图(我之前称为GdiFlush),屏幕截图就是纯黑色的(正如我所说,也不应该是这种情况,我之前检查了两个像素…)。 现在,回到最初的问题:这肯定是我的错,还是PrintWindow可能只是不时给出随机结果而不返回错误

好的,这是新代码:

    /* 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;
}