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
Asked
Active
Viewed 1,056 times
1
-
Do you want capture the complete screen or just a portion of it? What do you mean with process? – Aleph0 Jun 13 '19 at 10:48
-
You might also try to change the options of `grabWindow` in order to grab the complete window. Unfortunately, I didn't found a foolproof way to obtain the size increment necessary that is idependent of your current OS and your OS Settings. – Aleph0 Jun 13 '19 at 11:18
2 Answers
1
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();
}

Aleph0
- 5,816
- 4
- 29
- 80
0
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;
}

Serhiy Kulish
- 1,057
- 1
- 6
- 8