#include <iostream>
#include <windows.h>
using namespace std;
void CaptureScreenByGDI()
{
HDC hDC = CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
int nScreenWidth = GetDeviceCaps(hDC, HORZRES);
int nScreenHeight = GetDeviceCaps(hDC, VERTRES);
HDC hCompatibleDC = CreateCompatibleDC(hDC);
HBITMAP hBitmap = CreateCompatibleBitmap(hDC, nScreenWidth, nScreenHeight);
SelectObject(hCompatibleDC, hBitmap);
BitBlt(hCompatibleDC, 0, 0, nScreenWidth, nScreenHeight, hDC, 0, 0, SRCCOPY);
// 获取默认调色板
HPALETTE hPalette = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
BITMAP bitmap;
GetObject(hBitmap, sizeof(bitmap), (LPVOID)&bitmap);
// 初始化位图头信息
BITMAPINFOHEADER bitmapInfoHeader;
ZeroMemory(&bitmapInfoHeader, sizeof(BITMAPINFOHEADER));
bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfoHeader.biWidth = bitmap.bmWidth;
bitmapInfoHeader.biHeight = bitmap.bmHeight;
bitmapInfoHeader.biPlanes = 1;
bitmapInfoHeader.biBitCount = 24;
bitmapInfoHeader.biCompression = BI_RGB;
//计算信息头及颜色表大小
int nColors = (1 << bitmapInfoHeader.biBitCount);
if (nColors > 256)
nColors = 0;
DWORD dwLength = bitmapInfoHeader.biSize + nColors * sizeof(RGBQUAD);
HDC hTmpDC = GetDC(NULL);
hPalette = SelectPalette(hTmpDC, hPalette, FALSE);
RealizePalette(hTmpDC);
// 为信息头和颜色表分配内存
HANDLE hDIB = GlobalAlloc(GMEM_FIXED, dwLength);
if (!hDIB)
{
SelectPalette(hTmpDC, hPalette, FALSE);
ReleaseDC(NULL, hTmpDC);
return ;
}
// 获取位图数据
LPBITMAPINFOHEADER lpBitmapInfoHeader = (LPBITMAPINFOHEADER)hDIB;
*lpBitmapInfoHeader = bitmapInfoHeader;
// 调用GetBIDBits
BOOL b = GetDIBits(hTmpDC, hBitmap, 0L, (DWORD)bitmapInfoHeader.biHeight, (LPBYTE)NULL, (LPBITMAPINFO)lpBitmapInfoHeader, (DWORD)DIB_RGB_COLORS);
bitmapInfoHeader = *lpBitmapInfoHeader;
// 图像的每行都对齐32字节
if (bitmapInfoHeader.biSizeImage == 0)
{
bitmapInfoHeader.biSizeImage = ((((bitmapInfoHeader.biWidth * bitmapInfoHeader.biBitCount) + 31) & ~31) / 8) * bitmapInfoHeader.biHeight;
if (bitmapInfoHeader.biCompression != BI_RGB)
bitmapInfoHeader.biSizeImage = (bitmapInfoHeader.biSizeImage * 3) / 2;
}
// 重新分配内存大小
dwLength += bitmapInfoHeader.biSizeImage;
HANDLE hMem = NULL;
if (hMem = GlobalReAlloc(hDIB, dwLength, GMEM_MOVEABLE))
{
hDIB = hMem;
}
else
{
GlobalFree(hDIB);
SelectPalette(hTmpDC, hPalette, FALSE);
ReleaseDC(NULL, hTmpDC);
return ;
}
lpBitmapInfoHeader = (LPBITMAPINFOHEADER)hDIB;
b = GetDIBits(hTmpDC, hBitmap, 0L, (DWORD)bitmapInfoHeader.biHeight,
(LPBYTE)lpBitmapInfoHeader + (bitmapInfoHeader.biSize + nColors * sizeof(RGBQUAD)),
(LPBITMAPINFO)lpBitmapInfoHeader, (DWORD)DIB_RGB_COLORS);
if (!b)
{
GlobalFree(hDIB);
SelectPalette(hTmpDC, hPalette, FALSE);
ReleaseDC(NULL, hTmpDC);
return ;
}
SelectPalette(hTmpDC, hPalette, FALSE);
ReleaseDC(NULL, hTmpDC);
BITMAPFILEHEADER bitmapFileHeader;
ZeroMemory(&bitmapFileHeader, sizeof(BITMAPFILEHEADER));
bitmapFileHeader.bfType = (DWORD)0x4D42;
bitmapFileHeader.bfSize = 54 + bitmapInfoHeader.biSizeImage;
bitmapFileHeader.bfOffBits = 54;
DWORD written = 0;
HANDLE hFile = CreateFile(_T("D:\\CaptureScreenByGDI.bmp"), GENERIC_ALL, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return ;
}
b = WriteFile(hFile, &bitmapFileHeader, sizeof(BITMAPFILEHEADER), &written, NULL);
b = WriteFile(hFile, hDIB, bitmapFileHeader.bfSize, &written, NULL);
FlushFileBuffers(hFile);
CloseHandle(hFile);
return ;
}
GDI方式截取系统屏幕
最新推荐文章于 2023-08-06 16:24:16 发布
这段代码展示了如何利用GDI(图形设备接口)在Windows系统中捕获屏幕截图并保存为位图文件。通过创建设备上下文,获取屏幕尺寸,创建兼容位图,进行位块传送(BitBlt),实现屏幕内容的复制。最后将位图数据写入到.bmp文件中。
摘要由CSDN通过智能技术生成