简体   繁体   English

GetDIBits 在屏幕捕获中多次迭代后返回零 function

[英]GetDIBits Returns Zero after Many Iterations In Screen Capture function

I am using this code to capture screen and cursor.我正在使用此代码来捕获屏幕和 cursor。

// ConsoleApplication1.cpp : This file contains the 'main' function. Program execution begins and ends there.

#include <Windows.h>
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>

using namespace std;
using namespace cv;

HWND hwndDesktop = NULL;
bool flg;
CURSORINFO cursor;
ICONINFOEXW info;
BITMAP bmpCursor;
HDC hwindowDC, hwindowCompatibleDC;
HBITMAP hbwindow;
int height, width, srcheight, srcwidth;
Mat src;
BITMAPINFOHEADER  bi;
RECT windowsize;    

Mat hwnd2mat(HWND hwnd)
{
    src.create(height, width, CV_8UC4);

    int val = 0;
    // use the previously created device context with the bitmap
    HGDIOBJ hPrevBitmap = SelectObject(hwindowCompatibleDC, hbwindow);
    // copy from the window device context to the bitmap device context
    val = StretchBlt(hwindowCompatibleDC, 0, 0, width, height, hwindowDC, 0, 0, srcwidth, srcheight, SRCCOPY); //change SRCCOPY to NOTSRCCOPY for wacky colors !
    if (val <= 0) {
        DWORD error_ = GetLastError();
        cout << "error " << error_ << endl;
    }
    cursor = { sizeof(cursor) };
    ::GetCursorInfo(&cursor);
    if (cursor.flags == CURSOR_SHOWING and flg) {
        info = { sizeof(info) };
        ::GetIconInfoExW(cursor.hCursor, &info);
        const int x = cursor.ptScreenPos.x - windowsize.left - info.xHotspot;
        const int y = cursor.ptScreenPos.y - windowsize.top - info.yHotspot;
        bmpCursor = { 0 };
        val = ::GetObject(info.hbmColor, sizeof(bmpCursor), &bmpCursor);
        val = ::DrawIconEx(hwindowCompatibleDC, x, y, cursor.hCursor, bmpCursor.bmWidth, bmpCursor.bmHeight,
            0, NULL, DI_NORMAL);
        if (val <= 0) {
            DWORD error_ = GetLastError();
            cout << "error " << error_ << endl;
            flg = false;
        }
    }
    val = GetDIBits(hwindowCompatibleDC, hbwindow, 0, height, src.data, (BITMAPINFO *)&bi, DIB_RGB_COLORS);  //copy from hwindowCompatibleDC to hbwindow
    if (val <= 0) {
        DWORD error_ = GetLastError();
        cout << "error " << error_ << endl;
        GdiFlush();
        flg = false;
    }

    SelectObject(hwindowCompatibleDC, hPrevBitmap);

    return src;
}

int main(int argc, char **argv)
{
    flg = true;
    hwndDesktop = GetDesktopWindow();
    namedWindow("output", WINDOW_NORMAL);
    int key = 0;
    hwindowDC = GetDC(hwndDesktop);

    if (hwindowDC == NULL) {
        DWORD error_ = GetLastError();
        cout << "error " << error_ << endl;
    }

    hwindowCompatibleDC = CreateCompatibleDC(hwindowDC);
    if (hwindowCompatibleDC == NULL) {
        DWORD error_ = GetLastError();
        cout << "error " << error_ << endl;
    }
    SetStretchBltMode(hwindowCompatibleDC, COLORONCOLOR);

    GetClientRect(hwndDesktop, &windowsize);
    srcheight = windowsize.bottom;
    srcwidth = windowsize.right;
    height = windowsize.bottom / 1;  //change this to whatever size you want to resize to
    width = windowsize.right / 1;

    hbwindow = CreateCompatibleBitmap(hwindowDC, width, height);
    if (hbwindow == NULL) {
        DWORD error_ = GetLastError();
        cout << "error " << error_ << endl;
    }
    bi.biSize = sizeof(BITMAPINFOHEADER);    //http://msdn.microsoft.com/en-us/library/windows/window/dd183402%28v=vs.85%29.aspx
    bi.biWidth = width;
    bi.biHeight = -height;  //this is the line that makes it draw upside down or not
    bi.biPlanes = 1;
    bi.biBitCount = 32;
    bi.biCompression = BI_RGB;
    bi.biSizeImage = 0;
    bi.biXPelsPerMeter = 0;
    bi.biYPelsPerMeter = 0;
    bi.biClrUsed = 0;
    bi.biClrImportant = 0;

    while (key != 27)
    {
        Mat src = hwnd2mat(hwndDesktop);
        // you can do some image processing here
        imshow("output", src);
        key = waitKey(1); // you can change wait time
    }

}

The Screen Capture works perfectly, but always fails after screen capture of just more than 8 mins and 30 seconds.屏幕截图完美运行,但在屏幕截图超过 8 分 30 秒后总是失败。 After 8 min and 30 seconds GetDIBits starts to return 0. I am running this on a 64bit machine with windows 10 professional ediiton. 8 分 30 秒后,GetDIBits 开始返回 0。我正在使用 windows 10 专业版的 64 位机器上运行它。 This Issue seems to not apear if i remove the cursor capturing code.如果我删除 cursor 捕获代码,此问题似乎不会出现。

DeleteObject(info.hbmColor);
DeleteObject(info.hbmMask);

Adding these lines did the trick.添加这些行就可以了。 Thanks to Raymond Chen and IInspectable感谢Raymond ChenIInspectable

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM