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");
}