C++ 屏幕抓取代码及解析

代码

// An highlighted block
void GetScreenShot(void)
{
	BITMAPFILEHEADER bfHeader;
	BITMAPINFOHEADER biHeader;
	BITMAPINFO bInfo;
	HGDIOBJ hTempBitmap;
	HBITMAP hBitmap;
	BITMAP bAllDesktops;
	HDC hDC, hMemDC;
	LONG lWidth, lHeight;
	BYTE *bBits = NULL;
	HANDLE hHeap = GetProcessHeap();
	DWORD cbBits, dwWritten = 0;
	HANDLE hFile;
	INT x = GetSystemMetrics(SM_XVIRTUALSCREEN);
	INT y = GetSystemMetrics(SM_YVIRTUALSCREEN);

	ZeroMemory(&bfHeader, sizeof(BITMAPFILEHEADER));
	ZeroMemory(&biHeader, sizeof(BITMAPINFOHEADER));
	ZeroMemory(&bInfo, sizeof(BITMAPINFO));
	ZeroMemory(&bAllDesktops, sizeof(BITMAP));

	hDC = GetDC(NULL);
	hTempBitmap = GetCurrentObject(hDC, OBJ_BITMAP);
	GetObjectW(hTempBitmap, sizeof(BITMAP), &bAllDesktops);

	lWidth = bAllDesktops.bmWidth;
	lHeight = bAllDesktops.bmHeight;

	DeleteObject(hTempBitmap);

	bfHeader.bfType = (WORD)('B' | ('M' << 8));
	bfHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
	biHeader.biSize = sizeof(BITMAPINFOHEADER);
	biHeader.biBitCount = 24;
	biHeader.biCompression = BI_RGB;
	biHeader.biPlanes = 1;
	biHeader.biWidth = lWidth;
	biHeader.biHeight = lHeight;

	bInfo.bmiHeader = biHeader;

	cbBits = (((24 * lWidth + 31)&~31) / 8) * lHeight;

	hMemDC = CreateCompatibleDC(hDC);
	hBitmap = CreateDIBSection(hDC, &bInfo, DIB_RGB_COLORS, (VOID **)&bBits, NULL, 0);
	SelectObject(hMemDC, hBitmap);
	BitBlt(hMemDC, 0, 0, lWidth, lHeight, hDC, x, y, SRCCOPY);


	hFile = CreateFileW(L"screen.jpg", GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	WriteFile(hFile, &bfHeader, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
	WriteFile(hFile, &biHeader, sizeof(BITMAPINFOHEADER), &dwWritten, NULL);
	WriteFile(hFile, bBits, cbBits, &dwWritten, NULL);

	CloseHandle(hFile);

	DeleteDC(hMemDC);
	ReleaseDC(NULL, hDC);
	DeleteObject(hBitmap);

	//return hBitmapToMat(hBitmap);

}

用到的相关函数

  1. HDC GetDC(
    HWND hWnd
    );

该函数用于返回特定窗体的区域或者是整个屏幕。当 hWnd 句柄为NULL时,返回整个屏幕。

  1. HGDIOBJ GetCurrentObject(
    HDC hdc,
    UINT type
    );

该函数返回设备上下文对象的子对象的句柄。
其中 type 种类包括:

  • PARAMETERS
    Value Meaning
  • OBJ_BITMAP
    Returns the current selected bitmap.
  • OBJ_BRUSH
    Returns the current selected brush.
  • OBJ_COLORSPACE
    Returns the current color space.
  • OBJ_FONT
    Returns the current selected font.
  • OBJ_PAL
    Returns the current selected palette.
  • OBJ_PEN
    Returns the current selected pen.

可以看出 OBJ_BITMAP 可以返回设备上下文对应的BITMAP 对象。

  1. int GetObjectW(
    HANDLE h,
    int c,
    LPVOID pv
    );

该函数获取图形对象的相关信息。
在本示例中,该函数用于将对象句柄转换为 BITMAP 对象。

  1. HDC CreateCompatibleDC(
    HDC hdc
    );

该函数创建内存上下文。

  1. HBITMAP CreateDIBSection(
    HDC hdc,
    const BITMAPINFO *pbmi,
    UINT usage,
    VOID **ppvBits,
    HANDLE hSection,
    DWORD offset
    );

该函数创建 一个DIB 对象容器,以便将bitmap 写入。

  1. HGDIOBJ SelectObject(
    HDC hdc,
    HGDIOBJ h
    );

该函数用于将新创建的对象赋值到hdc 对象内。

  1. BOOL BitBlt(
    HDC hdc,
    int x,
    int y,
    int cx,
    int cy,
    HDC hdcSrc,
    int x1,
    int y1,
    DWORD rop
    );

从源对象将位图数据赋值到新创建的 HDC 对象中。
hdc 目标对象,hdcSrc 源对象。

总结

综上我们可以这样理解。 函数 GetDC 获得设备上下文(可以是窗口或者是整个屏幕),CreateCompatibleDC 创建一个内存上下文,CreateDIBSection 创建一个可访问的BITMAP容器。SelectObject 方法将容器绑定到内存上下文。BitBlt 方法将源设备上下文BITMAP数据赋值到新创建的内存上下文。 我们接下来就可以通过访问 hBitmap 来访问得到的图像数据。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值