MFC截图

void CaptureWindow(HWND hWnd, CString strFilePath)
{
	CRect rect;
	::GetWindowRect(hWnd, &rect); // 获取窗口位置和大小(包括边框)

	HDC hWindowDC = GetWindowDC(hWnd);
	HDC hCaptureDC = CreateCompatibleDC(hWindowDC);
	HBITMAP hCaptureBitmap = CreateCompatibleBitmap(hWindowDC, rect.Width(), rect.Height());
	HGDIOBJ hOldBitmap = SelectObject(hCaptureDC, hCaptureBitmap);

	// 将窗口内容复制到兼容 DC
	PrintWindow(hWnd, hCaptureDC, PW_CLIENTONLY); // 或不用 PW_CLIENTONLY 截取整个窗口(含标题栏)

	// 保存图像
	CImage image;
	image.Attach(hCaptureBitmap);
	image.Save(strFilePath);
	image.Detach();

	// 清理
	SelectObject(hCaptureDC, hOldBitmap);
	DeleteObject(hCaptureBitmap);
	DeleteDC(hCaptureDC);
	ReleaseDC(hWnd, hWindowDC);
}
void CaptureScreen(CString strFilePath)
{
	// 获取桌面窗口句柄
	HWND hDesktopWnd = GetDesktopWindow();
	HDC hDesktopDC = GetDC(hDesktopWnd);
	HDC hCaptureDC = CreateCompatibleDC(hDesktopDC);

	// 获取屏幕尺寸
	int nWidth = GetSystemMetrics(SM_CXSCREEN);
	int nHeight = GetSystemMetrics(SM_CYSCREEN);

	// 创建兼容位图
	HBITMAP hCaptureBitmap = CreateCompatibleBitmap(hDesktopDC, nWidth, nHeight);
	HGDIOBJ hOldBitmap = SelectObject(hCaptureDC, hCaptureBitmap);

	// 执行位块传输(BitBlt)
	BitBlt(hCaptureDC, 0, 0, nWidth, nHeight, hDesktopDC, 0, 0, SRCCOPY | CAPTUREBLT);

	// 恢复旧位图
	SelectObject(hCaptureDC, hOldBitmap);

	// 保存位图为文件(需要额外代码,例如使用 CImage 或自定义保存逻辑)
	CImage image;
	image.Attach(hCaptureBitmap);
	image.Save(strFilePath); // 支持 BMP、JPG、PNG 等(取决于 GDI+ 是否启用)
	image.Detach();

	// 清理资源
	DeleteObject(hCaptureBitmap);
	DeleteDC(hCaptureDC);
	ReleaseDC(hDesktopWnd, hDesktopDC);
}
#include <windows.h>
#include <tchar.h> // 支持 UNICODE 和 ANSI 切换

void CaptureScreenToBMP(LPCTSTR lpszFilePath)
{
	// 1. 获取屏幕尺寸
	int nWidth = GetSystemMetrics(SM_CXSCREEN);
	int nHeight = GetSystemMetrics(SM_CYSCREEN);

	// 2. 获取桌面 DC
	HDC hScreenDC = GetDC(NULL); // NULL 表示整个屏幕
	HDC hMemDC = CreateCompatibleDC(hScreenDC);

	// 3. 创建 DIB(设备无关位图),以便能获取像素数据
	BITMAPINFO bmi = { 0 };
	bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmi.bmiHeader.biWidth = nWidth;
	bmi.bmiHeader.biHeight = -nHeight; // 负值表示 top-down DIB(原点在左上角)
	bmi.bmiHeader.biPlanes = 1;
	bmi.bmiHeader.biBitCount = 32;     // 32位色(含 alpha,但通常忽略)
	bmi.bmiHeader.biCompression = BI_RGB;

	void* pBits = nullptr;
	HBITMAP hDIBBitmap = CreateDIBSection(hMemDC, &bmi, DIB_RGB_COLORS, &pBits, NULL, 0);
	if (!hDIBBitmap)
	{
		ReleaseDC(NULL, hScreenDC);
		DeleteDC(hMemDC);
		return;
	}

	HGDIOBJ hOldBitmap = SelectObject(hMemDC, hDIBBitmap);

	// 4. 将屏幕内容拷贝到内存 DC
	BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScreenDC, 0, 0, SRCCOPY | CAPTUREBLT);

	// 5. 准备 BMP 文件头
	BITMAPFILEHEADER bfh = { 0 };
	bfh.bfType = 0x4D42; // 'BM'
	DWORD dwBmpSize = ((nWidth * 32 + 31) / 32) * 4 * nHeight; // 每行字节对齐到 4 字节
	bfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwBmpSize;
	bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

	// 6. 写入文件
	HANDLE hFile = CreateFile(
		lpszFilePath,
		GENERIC_WRITE,
		0,
		NULL,
		CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL,
		NULL
	);

	if (hFile != INVALID_HANDLE_VALUE)
	{
		DWORD dwWritten = 0;
		WriteFile(hFile, &bfh, sizeof(bfh), &dwWritten, NULL);
		WriteFile(hFile, &bmi.bmiHeader, sizeof(BITMAPINFOHEADER), &dwWritten, NULL);
		WriteFile(hFile, pBits, dwBmpSize, &dwWritten, NULL);
		CloseHandle(hFile);
	}

	// 7. 清理资源
	SelectObject(hMemDC, hOldBitmap);
	DeleteObject(hDIBBitmap);
	DeleteDC(hMemDC);
	ReleaseDC(NULL, hScreenDC);
}
void CtestcaptureDlg::OnBnClickedOk()
{
	CaptureWindow(m_hWnd, L"d:\\aa.bmp");
	CaptureScreen(L"d:\\bbb.bmp");
	CaptureScreenToBMP(L"d:\\ccc.bmp");
}

  

posted @ 2026-05-13 14:03  leochan007  阅读(12)  评论(0)    收藏  举报