在 Windows 使用 Qt 在 c++ 中打开进程并捕获其区域的屏幕
open a process and capture screen of its area in c++ on Windows using Qt
如何在 Windows 上用 c++ 打开进程并将其区域的屏幕捕获到图像文件中?
我正在使用 Qt,但 Qt 似乎没有 API。
所以我想知道是否有 API 或 lib 可以做到这一点。
谢谢
我的第一次尝试是这样的。它只捕获 window 的内容,而不是 window 本身。您还想捕获整个 window 或屏幕吗?
#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();
}
您可以使用 Windows API
1.Take 进程号
qint64 pid = 0;
QProcess::startDetached("calc.exe", QStringList(), QString(), &pid);
2.Take window 来自进程 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 您的 HWND
屏幕截图并使用此功能保存在文件中
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;
}
如何在 Windows 上用 c++ 打开进程并将其区域的屏幕捕获到图像文件中? 我正在使用 Qt,但 Qt 似乎没有 API。 所以我想知道是否有 API 或 lib 可以做到这一点。 谢谢
我的第一次尝试是这样的。它只捕获 window 的内容,而不是 window 本身。您还想捕获整个 window 或屏幕吗?
#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();
}
您可以使用 Windows API
1.Take 进程号
qint64 pid = 0;
QProcess::startDetached("calc.exe", QStringList(), QString(), &pid);
2.Take window 来自进程 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 您的 HWND
屏幕截图并使用此功能保存在文件中
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;
}