C++使用Win32GDI DC进行屏幕截图
代码
#include <windows.h>
#include <Psapi.h>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <memory>
#include <string>
#include <thread>
#include <dxgi.h>
#include <d3d11.h>
#include <wrl.h>
BOOL SaveBitmapToFile(HBITMAP hBitmap, LPCTSTR filename)
{
BITMAP bmp;
GetObject(hBitmap, sizeof(BITMAP), &bmp);
DWORD dwBmpSize = ((bmp.bmWidth * bmp.bmBitsPixel + 31) / 32) * 4 * bmp.bmHeight;
HANDLE hDIB = GlobalAlloc(GHND, dwBmpSize);
char *lpbitmap = (char *)GlobalLock(hDIB);
BITMAPINFOHEADER bi;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bmp.bmWidth;
bi.biHeight = bmp.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = 24;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrImportant = 0;
bi.biClrUsed = 0;
// 获取位图数据
GetDIBits(GetDC(NULL), hBitmap, 0, (UINT)bmp.bmHeight, lpbitmap, (BITMAPINFO *)&bi, DIB_RGB_COLORS);
// 创建文件并写入数据
HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwWritten;
BITMAPFILEHEADER bfh;
bfh.bfType = 0x4D42; // BM
bfh.bfSize = sizeof(BITMAPFILEHEADER) + dwBmpSize;
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
WriteFile(hf, (LPSTR)&bfh, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
WriteFile(hf, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwWritten, NULL);
WriteFile(hf, lpbitmap, dwBmpSize, &dwWritten, NULL);
// 清理
GlobalUnlock(hDIB);
GlobalFree(hDIB);
CloseHandle(hf);
return TRUE;
}
bool CaptureScreen(const wchar_t *filePath)
{
// 获取屏幕宽高
int width = GetSystemMetrics(SM_CXSCREEN);
int height = GetSystemMetrics(SM_CYSCREEN);
// 创建屏幕DC
HDC hScreenDC = GetDC(NULL);
if (!hScreenDC)
{
std::cerr << "Failed to get screen DC" << std::endl;
return 1;
}
// 创建一个与屏幕DC兼容的内存DC
HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
if (!hMemoryDC)
{
std::cerr << "Failed to create memory DC" << std::endl;
ReleaseDC(NULL, hScreenDC);
return 1;
}
// 创建一个与屏幕兼容的位图
HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, width, height);
if (!hBitmap)
{
std::cerr << "Failed to create bitmap" << std::endl;
DeleteDC(hMemoryDC);
ReleaseDC(NULL, hScreenDC);
return 1;
}
// 将位图选入内存DC
HGDIOBJ old_obj = SelectObject(hMemoryDC, hBitmap);
// 捕获屏幕到内存DC
if (!BitBlt(hMemoryDC, 0, 0, width, height, hScreenDC, 0, 0, SRCCOPY))
{
std::cerr << "Failed to capture screen" << std::endl;
SelectObject(hMemoryDC, old_obj);
DeleteObject(hBitmap);
DeleteDC(hMemoryDC);
ReleaseDC(NULL, hScreenDC);
return 1;
}
// 保存位图
if (!SaveBitmapToFile(hBitmap, filePath))
{
std::cerr << "Failed to save bitmap" << std::endl;
}
// 清理资源
SelectObject(hMemoryDC, old_obj);
DeleteObject(hBitmap);
DeleteDC(hMemoryDC);
ReleaseDC(NULL, hScreenDC);
return 0;
}
int main(void)
{
CaptureScreen(L"E:\\output.bmp");
return 0;
}
本文为博主总结文章,欢迎转载,请注明出处。