一、截全屏
保存为.bmp格式和保存为.png格式
完整代码:
#include<windows.h>
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment(lib, "gdiplus.lib")
int GetEncoderClsid(const WCHAR *format, CLSID *pClsid)
{
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array in bytes
ImageCodecInfo* pImageCodecInfo = NULL;
GetImageEncodersSize(&num, &size);
if (size == 0)
return -1; // Failure
pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if (pImageCodecInfo == NULL)
return -1; // Failure
GetImageEncoders(num, size, pImageCodecInfo);
for (UINT j = 0; j < num; ++j)
{
if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0)
{
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j; // Success
}
}
free(pImageCodecInfo);
return -1; // Failure
}
//屏幕截图保存为bmp格式
void ScreenshotBmp()
{
HWND hwnd = GetHWND();
RECT rcClient;
GetClientRect(hwnd, &rcClient);
//1、获得指定窗口的dc(源dc)
//注意GetWindowDC会把窗口的标题栏也同时截图,如果不需要窗口的标题就使用GetDC(hwnd)
HDC sourceDC = GetWindowDC(hwnd);
//2、根据源dc创建兼容内存DC
HDC momDC;//内存DC
momDC = ::CreateCompatibleDC(sourceDC);
//3、根据源dc创建兼容位图
HBITMAP memBitmap;
memBitmap = ::CreateCompatibleBitmap(sourceDC, rcClient.right- rcClient.left, rcClient.bottom - rcClient.top);
//4、将兼容位图写入内存dc
SelectObject(momDC, memBitmap);
//5、截图
BitBlt(momDC, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, sourceDC, rcClient.left, rcClient.top, SRCCOPY);
//6、以下代码保存截图信息到文件中
//6.1获得位图信息
BITMAP bmp;
GetObject(memBitmap, sizeof(BITMAP), &bmp);
//6.2图片保存路径和方式
FILE* fp;
fopen_s(&fp, "test.bmp", "w+b");
//6.3创建位图文件头
//位图文件头设置默认值为0
BITMAPFILEHEADER bfh = { 0 };
//到位图数据的偏移量(此步骤固定,位图编译量即为位图文件头 + 位图信息头 + 调色板的大小,调色板设置为0)
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
//文件总的大小
bfh.bfSize = bfh.bfOffBits + bmp.bmWidthBytes * bmp.bmHeight;
//bfType固定为BM,(WORD)0x4d42表示为BM
bfh.bfType = (WORD)0x4d42;
//6.4创建文件信息头
//位图信息头,默认设置为0
BITMAPINFOHEADER bih = { 0 };
//每个像素字节大小
bih.biBitCount = bmp.bmBitsPixel;
bih.biCompression = BI_RGB;
//高度
bih.biHeight = bmp.bmHeight;
bih.biPlanes = 1;
bih.biSize = sizeof(BITMAPINFOHEADER);
//图像数据大小
bih.biSizeImage = bmp.bmWidthBytes * bmp.bmHeight;
//宽度
bih.biWidth = bmp.bmWidth;
//6.5写入位图文件头
fwrite(&bfh, 1, sizeof(BITMAPFILEHEADER), fp);
//6.6写入位图信息头
fwrite(&bih, 1, sizeof(BITMAPINFOHEADER), fp);
//6.7申请内存保存位图数据
byte* p = new byte[bmp.bmWidthBytes * bmp.bmHeight];
//6.8获取位图数据
GetDIBits(momDC, (HBITMAP)memBitmap, 0, rcClient.bottom - rcClient.top, p,
(LPBITMAPINFO)&bih, DIB_RGB_COLORS);
//6.9写入位图数据
fwrite(p, 1, bmp.bmWidthBytes * bmp.bmHeight, fp);
//6.10先删除开辟的内存,然后关闭文件
delete[] p;
fclose(fp);
//7删除链接
//7.1删除创建的位图
DeleteObject(memBitmap);
//7.2删除创建的兼容内存DC
DeleteDC(momDC);
//7.3#释放窗口DC
ReleaseDC(hwnd, sourceDC);
}
//屏幕截图保存为png格式
void ScreenshotPng()
{
HWND hwnd = GetHWND();
HDC hdcScreen = GetDC(hwnd);
HDC hdcWindow = CreateCompatibleDC(hdcScreen);
RECT rcClient;
GetClientRect(hwnd, &rcClient);
HBITMAP hbmScreen = CreateCompatibleBitmap(hdcScreen, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top);
SelectObject(hdcWindow, hbmScreen);
// 拷贝屏幕内容到设备上下文
BitBlt(hdcWindow, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, hdcScreen, rcClient.left, rcClient.top, SRCCOPY);
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
Gdiplus::Bitmap bmp(hbmScreen, NULL);
CLSID pngClsid;
int i = GetEncoderClsid(L"image/png", &pngClsid);
bmp.Save(L"test.png", &pngClsid, NULL);
GdiplusShutdown(gdiplusToken);
// 释放资源
DeleteObject(hbmScreen);
DeleteDC(hdcWindow);
ReleaseDC(hwnd, hdcScreen);
}
二、不截全屏
void system::ScreenshotJpg(string strImageName, HWND hwnd, int nTopPadding/* = 0*/, int nBottomPadding/* = 0*/, int nLeftPadding/* = 0*/, int nRightPadding/* = 0*/)
{
HDC hdcScreen = GetDC(hwnd);
HDC hdcWindow = CreateCompatibleDC(hdcScreen);
RECT rcClient;
GetClientRect(hwnd, &rcClient);
rcClient.top += nTopPadding;
rcClient.bottom -= nBottomPadding;
rcClient.left += nLeftPadding;
rcClient.right -= nRightPadding;
HBITMAP hbmScreen = CreateCompatibleBitmap(hdcScreen, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top);
SelectObject(hdcWindow, hbmScreen);
// 拷贝屏幕内容到设备上下文
BitBlt(hdcWindow, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, hdcScreen, rcClient.left, rcClient.top, SRCCOPY);
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
Gdiplus::Bitmap bmp(hbmScreen, NULL);
CLSID pngClsid;
int i = GetEncoderClsid(L"image/png", &pngClsid);
strImageName.append(".png");
bmp.Save(convert::ANSI2Unicode(strImageName.c_str()).c_str(), &pngClsid, NULL);
GdiplusShutdown(gdiplusToken);
// 释放资源
DeleteObject(hbmScreen);
DeleteDC(hdcWindow);
ReleaseDC(hwnd, hdcScreen);
}
参考:
1.c++ 使用win api截图指定窗口并保存图片_截图别的窗口vc-CSDN博客
2.在Windows中使用C++截取窗口截图的最佳方法是什么?_在windows中复制fork()的最佳方法是什么?_在C++中清除容器的最佳方法是什么? - 腾讯云开发者社区 - 腾讯云