open a process and capture screen of its area in c++ on Windows using Qt

1.1k Views Asked by At

how to open a process and capture the screen of its area into a image file in c++ on Windows? i am using Qt, but it seems Qt doesnot have API for this. so i want to know is there any API or lib to do this. thank you

2

There are 2 best solutions below

0
Aleph0 On BEST ANSWER

My first attempt would be something like this. It only captures the content of the window and not the window by itself. Do you also want to capture the whole window or screen?

#include <QApplication>
#include <QTreeView>
#include <QScreen>
#include <QPixmap>
#include <QTimer>

int main(int argc, char** args) {
    QApplication app(argc, args);
    auto view = new QTreeView;
    view->show();
    QTimer::singleShot(10, [&]() {
        auto screen = app.primaryScreen();
        auto pixmap = screen->grabWindow(view->winId());
        pixmap.save("Screenshot.png");
    });
    app.exec();
}
0
Serhiy Kulish On

You can do this with Windows API

1.Take process id

qint64 pid = 0;
QProcess::startDetached("calc.exe", QStringList(), QString(), &pid);

2.Take window handler from process id

HWND g_HWND=NULL;
BOOL CALLBACK EnumWindowsProcMy(HWND hwnd,LPARAM lParam)
{
    DWORD lpdwProcessId;
    GetWindowThreadProcessId(hwnd,&lpdwProcessId);
    if(lpdwProcessId==lParam)
    {
        g_HWND = hwnd;
        return FALSE;
    }
    return TRUE;
}

g_HWND = NULL;
EnumWindows(EnumWindowsProcMy,pid);

3.Take screenshot from your HWND and save in file with this function

int WinSysUtils::CaptureAnImage(HWND hWnd, const wchar_t *fileName)
{
    HDC dcScreen = GetDC(hWnd);
    HDC dcTarget = CreateCompatibleDC(dcScreen);

    RECT rect;
    GetClientRect(hWnd, &rect);

    int width = rect.right - rect.left;
    int height = rect.bottom - rect.top;

    HBITMAP bmpTarget = CreateCompatibleBitmap(dcScreen, width, height);
    HGDIOBJ oldBmp = SelectObject(dcTarget, bmpTarget);

    BitBlt(dcTarget, 0, 0, width, height, dcScreen, 0, 0, SRCCOPY | CAPTUREBLT);
    SelectObject(dcTarget, oldBmp);

    // Get the BITMAP from the HBITMAP
    BITMAP bmpScreen;
    GetObject(bmpTarget, sizeof(BITMAP), &bmpScreen);

    BITMAPFILEHEADER   bmfHeader;
    BITMAPINFOHEADER   bi;

    bi.biSize = sizeof(BITMAPINFOHEADER);
    bi.biWidth = bmpScreen.bmWidth;
    bi.biHeight = bmpScreen.bmHeight;
    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;

    DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight;

    // Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that
    // call HeapAlloc using a handle to the process's default heap. Therefore, GlobalAlloc and LocalAlloc
    // have greater overhead than HeapAlloc.
    HANDLE hDIB = GlobalAlloc(GHND, dwBmpSize);
    char *lpbitmap = (char *)GlobalLock(hDIB);

    // Gets the "bits" from the bitmap and copies them into a buffer
    // which is pointed to by lpbitmap.
    GetDIBits(dcScreen, bmpTarget, 0,
              (UINT)bmpScreen.bmHeight,
              lpbitmap,
              (BITMAPINFO *)&bi, DIB_RGB_COLORS);

    // A file is created, this is where we will save the screen capture.
    HANDLE hFile = CreateFile(fileName,
            GENERIC_WRITE,
            0,
            NULL,
            CREATE_ALWAYS,
            FILE_ATTRIBUTE_NORMAL, NULL);

    // Add the size of the headers to the size of the bitmap to get the total file size
    DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

    //Offset to where the actual bitmap bits start.
    bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);

    //Size of the file
    bmfHeader.bfSize = dwSizeofDIB;

    //bfType must always be BM for Bitmaps
    bmfHeader.bfType = 0x4D42; //BM

    DWORD dwBytesWritten = 0;
    WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
    WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
    WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);

    //Unlock and Free the DIB from the heap
    GlobalUnlock(hDIB);
    GlobalFree(hDIB);

    //Close the handle for the file that was created
    CloseHandle(hFile);

    DeleteDC(dcTarget);
    DeleteDC(dcScreen);

    return 0;
}