#ifndef SCREEN_CAPTURER_H
#define SCREEN_CAPTURER_H
#include <string>
#include <gdiplus.h>
class ScreenCapturer {
public:
ScreenCapturer();
~ScreenCapturer();
// 截图并保存为PNG
bool captureToFile(const std::string& filename,
int x = 0, int y = 0,
int width = -1, int height = -1);
// 截图并转换为十六进制字符串
std::string captureToHex(int x = 0, int y = 0,
int width = -1, int height = -1);
private:
ULONG_PTR gdiplusToken;
// 保存位图为PNG
bool saveBitmapAsPng(HBITMAP hBitmap, const std::string& filename);
// 获取图像编码器的CLSID
bool getEncoderClsid(const WCHAR* format, CLSID* pClsid);
};
#endif // SCREEN_CAPTURER_H
#include "ScreenCapturer.h"
#include "CommonUtils.h"
#include <Windows.h>
#include <fstream>
#include <vector>
#include <sstream>
ScreenCapturer::ScreenCapturer() {
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
}
ScreenCapturer::~ScreenCapturer() {
Gdiplus::GdiplusShutdown(gdiplusToken);
}
bool ScreenCapturer::captureToFile(const std::string& filename,
int x, int y,
int width, int height) {
// 获取屏幕尺寸
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
// 如果未指定尺寸,则使用全屏
if (width <= 0) width = screenWidth - x;
if (height <= 0) height = screenHeight - y;
// 确保区域在屏幕范围内
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x + width > screenWidth) width = screenWidth - x;
if (y + height > screenHeight) height = screenHeight - y;
if (width <= 0 || height <= 0) return false;
HDC hdcScreen = GetDC(NULL);
HDC hdcMem = CreateCompatibleDC(hdcScreen);
HBITMAP hBitmap = CreateCompatibleBitmap(hdcScreen, width, height);
// 使用全局命名空间限定符避免冲突
::SelectObject(hdcMem, hBitmap);
// 截取指定区域
BitBlt(hdcMem, 0, 0, width, height, hdcScreen, x, y, SRCCOPY);
// 保存为PNG
bool result = saveBitmapAsPng(hBitmap, filename);
// 清理资源
DeleteObject(hBitmap);
DeleteDC(hdcMem);
ReleaseDC(NULL, hdcScreen);
return result;
}
std::string ScreenCapturer::captureToHex(int x, int y,
int width, int height) {
// 创建临时文件
char tempPath[MAX_PATH];
char tempFile[MAX_PATH];
GetTempPathA(MAX_PATH, tempPath);
GetTempFileNameA(tempPath, "cap", 0, tempFile);
// 截图到临时文件
if (!captureToFile(tempFile, x, y, width, height)) {
return "";
}
// 读取文件内容
std::ifstream file(tempFile, std::ios::binary);
if (!file) {
return "";
}
// 获取文件大小
file.seekg(0, std::ios::end);
std::streampos fileSize = file.tellg();
file.seekg(0, std::ios::beg);
// 读取文件内容
std::vector<char> buffer(static_cast<size_t>(fileSize));
if (!file.read(&buffer[0], fileSize)) {
return "";
}
// 转换为十六进制
std::ostringstream hexStream;
for (size_t i = 0; i < static_cast<size_t>(fileSize); i++) {
unsigned char c = static_cast<unsigned char>(buffer[i]);
hexStream << to_hex_string(c);
}
// 删除临时文件
DeleteFileA(tempFile);
return hexStream.str();
}
bool ScreenCapturer::saveBitmapAsPng(HBITMAP hBitmap, const std::string& filename) {
Gdiplus::Bitmap bitmap(hBitmap, NULL);
// 获取PNG编码器
CLSID pngClsid;
if (!getEncoderClsid(L"image/png", &pngClsid)) {
return false;
}
// 转换为宽字符串
std::wstring wfilename(filename.begin(), filename.end());
Gdiplus::Status status = bitmap.Save(wfilename.c_str(), &pngClsid, NULL);
return status == Gdiplus::Ok;
}
bool ScreenCapturer::getEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
UINT num = 0; // 编码器数量
UINT size = 0; // 编码器大小
Gdiplus::GetImageEncodersSize(&num, &size);
if (size == 0) return false;
Gdiplus::ImageCodecInfo* pImageCodecInfo = (Gdiplus::ImageCodecInfo*)malloc(size);
if (pImageCodecInfo == NULL) return false;
Gdiplus::GetImageEncoders(num, size, pImageCodecInfo);
for (UINT i = 0; i < num; i++) {
if (wcscmp(pImageCodecInfo[i].MimeType, format) == 0) {
*pClsid = pImageCodecInfo[i].Clsid;
free(pImageCodecInfo);
return true;
}
}
free(pImageCodecInfo);
return false;
}Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); 你这报错 提示没有成员
最新发布