如何使用c ++为最小尺寸的窗口制作屏幕截图
Posted
技术标签:
【中文标题】如何使用c ++为最小尺寸的窗口制作屏幕截图【英文标题】:how to make a screenshot for windows with minimum size with c ++ 【发布时间】:2020-01-29 11:40:19 【问题描述】:我实现了一个截屏程序,但问题是图像大小大于 6 MB。
我想进行修正以最小化图像尺寸。
这是我的功能
BOOL CALLBACK MonitorEnumProcCallback( HMONITOR hMonitor, HDC DevC,LPRECT lprcMonitor,LPARAM dwData)
const char*BmpName;
string BmpNameString;
BmpNameString="screen.jpeg";
BmpName= BmpNameString.c_str();
MONITORINFO info;
info.cbSize = sizeof(MONITORINFO);
BOOL monitorInfo = GetMonitorInfo(hMonitor, &info);
if (monitorInfo)
DWORD Width = info.rcMonitor.right - info.rcMonitor.left;
DWORD Height = info.rcMonitor.bottom - info.rcMonitor.top;
DWORD FileSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 3 * Width * Height;
char *BmpFileData = (char*)GlobalAlloc(0x0040, FileSize);
PBITMAPFILEHEADER BFileHeader = (PBITMAPFILEHEADER)BmpFileData;
PBITMAPINFOHEADER BInfoHeader = (PBITMAPINFOHEADER)&BmpFileData[sizeof(BITMAPFILEHEADER)];
BFileHeader->bfType = 0x4D42; // BM
BFileHeader->bfSize = sizeof(BITMAPFILEHEADER);
BFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
BInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
BInfoHeader->biPlanes = 1;
BInfoHeader->biBitCount = 24;
BInfoHeader->biCompression = BI_RGB;
BInfoHeader->biHeight = Height;
BInfoHeader->biWidth = Width;
RGBTRIPLE *Image = (RGBTRIPLE*)&BmpFileData[sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)];
RGBTRIPLE color;
HDC CaptureDC = CreateCompatibleDC(DevC);
HBITMAP CaptureBitmap = CreateCompatibleBitmap(DevC, Width, Height);
SelectObject(CaptureDC, CaptureBitmap);
BitBlt(CaptureDC, 0, 0, Width, Height, DevC, info.rcMonitor.left, info.rcMonitor.top, SRCCOPY | CAPTUREBLT);
GetDIBits(CaptureDC, CaptureBitmap, 0, Height, Image, (LPBITMAPINFO)BInfoHeader, DIB_RGB_COLORS);
DWORD Junk;
HANDLE FH = CreateFileA(BmpName, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0);
WriteFile(FH, BmpFileData, FileSize, &Junk, 0);
CloseHandle(FH);
GlobalFree(BmpFileData);
return TRUE;
data
【问题讨论】:
什么是最小尺寸?最小的图像大小为 0x0,接近 0 字节(只有一些元信息) 使用 jpeg 等有损压缩方法进行转换。 @ThomasSablik 最小尺寸?大小为 1 MB 压缩您的图像数据。简单地传递压缩格式的文件名不会神奇地压缩图像数据。而是通过 Windows 映像组件使用 Windows 上可用的编解码器之一。 【参考方案1】:如果你不介意的话,可以使用下面的GDI+方法得到一个比较小的尺寸:
#include<windows.h>
#include <iostream>
#include <string.h>
#include <gdiplus.h>
#include <stdio.h>
using namespace Gdiplus;
using namespace std;
#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
BOOL CALLBACK MonitorEnumProcCallback(HMONITOR hMonitor, HDC DevC, LPRECT lprcMonitor, LPARAM dwData)
wstring BmpNameString = L"screen.jpeg";
MONITORINFO info;
info.cbSize = sizeof(MONITORINFO);
BOOL monitorInfo = GetMonitorInfo(hMonitor, &info);
if (monitorInfo)
DWORD Width = info.rcMonitor.right - info.rcMonitor.left;
DWORD Height = info.rcMonitor.bottom - info.rcMonitor.top;
//DWORD FileSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 3 * Width * Height;
//char* BmpFileData = (char*)GlobalAlloc(0x0040, FileSize);
//PBITMAPFILEHEADER BFileHeader = (PBITMAPFILEHEADER)BmpFileData;
//PBITMAPINFOHEADER BInfoHeader = (PBITMAPINFOHEADER)&BmpFileData[sizeof(BITMAPFILEHEADER)];
//BFileHeader->bfType = 0x4D42; // BM
//BFileHeader->bfSize = sizeof(BITMAPFILEHEADER);
//BFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
//BInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
//BInfoHeader->biPlanes = 1;
//BInfoHeader->biBitCount = 24;
//BInfoHeader->biCompression = BI_RLE8;
//BInfoHeader->biHeight = Height;
//BInfoHeader->biWidth = Width;
//RGBTRIPLE* Image = (RGBTRIPLE*)&BmpFileData[sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)];
//RGBTRIPLE color;
HDC CaptureDC = CreateCompatibleDC(DevC);
HBITMAP CaptureBitmap = CreateCompatibleBitmap(DevC, Width, Height);
HGDIOBJ old_obj = SelectObject(CaptureDC, CaptureBitmap);
BitBlt(CaptureDC, 0, 0, Width, Height, DevC, info.rcMonitor.left, info.rcMonitor.top, SRCCOPY | CAPTUREBLT);
//GetDIBits(CaptureDC, CaptureBitmap, 0, Height, Image, (LPBITMAPINFO)BInfoHeader, DIB_RGB_COLORS);
/*DWORD Junk;
HANDLE FH = CreateFileA(BmpName, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0);
WriteFile(FH, BmpFileData, FileSize, &Junk, 0);
CloseHandle(FH);
GlobalFree(BmpFileData);*/
Gdiplus::Bitmap bitmap(CaptureBitmap, NULL);
CLSID pngClsid;
GetEncoderClsid(L"image/jpeg", &pngClsid);
bitmap.Save(BmpNameString.c_str(), &pngClsid, NULL);
SelectObject(CaptureDC, old_obj);
DeleteDC(CaptureDC);
ReleaseDC(NULL, DevC);
DeleteObject(CaptureBitmap);
return TRUE;
int main()
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
HDC hdc = GetDC(NULL);
EnumDisplayMonitors(hdc,NULL, MonitorEnumProcCallback,NULL);
ReleaseDC(NULL,hdc);
GdiplusShutdown(gdiplusToken);
return 0;
【讨论】:
以上是关于如何使用c ++为最小尺寸的窗口制作屏幕截图的主要内容,如果未能解决你的问题,请参考以下文章