C++实现屏幕截图
上回分享了一个全屏截图的代码,保存为BMP,参考:C++实现屏幕截图(全屏截图)
实际使用的过程中我发现截图文件实在大,无奈又整成了PNG截图,现在分享出来。
MakePNG.h
//MakePNG.h #pragmaonce #includeusingnamespaceGdiplus; #pragmacomment(lib,"GdiPlus.lib") classCMakePNG { public: CMakePNG(void); ~CMakePNG(void); BOOLMakePNG(HDChDC,CRectrect,CStringstrFilePath); BOOLBMptoPNG(LPCWSTRStrBMp,LPCWSTRStrPNG); BOOLPNGtoBMp(LPCWSTRStrPNG,LPCWSTRStrBMp); BOOLGetEncoderClsid(WCHAR*pFormat,CLSID*pClsid); private: GdiplusStartupInputm_gdiplusStartupInput; ULONG_PTRm_pGdiToken; };
MakePNG.cpp
//MakePNG.cpp
#include"StdAfx.h"
#include"MakePNG.h"
CMakePNG::CMakePNG(void)
{
GdiplusStartup(&m_pGdiToken,&m_gdiplusStartupInput,NULL);
}
CMakePNG::~CMakePNG(void)
{
}
/***************************************************************************/
/*功能:根据rect屏幕抓图,保存为文件名为strFilePath的PNG图像文件*/
/*输入参数:HDChDC屏幕HDC;*/
/*CRectrect需要的矩形;*/
/*CStringstrFilePath保存文件全路径(含后缀名);*/
/***************************************************************************/
BOOLCMakePNG::MakePNG(HDChDC,CRectrect,CStringstrFilePath)
{
BITMAPbmp;
PBITMAPINFOpbmi;
PBITMAPINFOHEADERpbih;//bitmapinfo-header
BITMAPFILEHEADERhdr;//bitmapfile-header
WORDcClrBits;
LPBYTElpBits;//memorypointer
DWORDdwTmp;
DWORDcb;//incrementalcountofbytes
BYTE*hp;//bytepointer
HANDLEhfile;//filehandle
CStringszBMPFilename=strFilePath.Left(strFilePath.GetLength()-3)+_T("bmp");//先保存成位图
HDChdcCompatible=CreateCompatibleDC(hDC);
HBITMAPhbmScreen=CreateCompatibleBitmap(hDC,rect.Width(),rect.Height());
if(hbmScreen==NULL)
{
AfxMessageBox(_T("CreateCompatibleBitmap()error"));
returnFALSE;
}
//SelectthebitmapsintothecompatibleDC.
if(!SelectObject(hdcCompatible,hbmScreen))
{
AfxMessageBox(_T("CompatibleBitmapSelectionerror"));
returnFALSE;
}
//Copycolordatafortheentiredisplayintoa
//bitmapthatisselectedintoacompatibleDC.
if(!BitBlt(hdcCompatible,
0,0,
rect.Width(),rect.Height(),
hDC,
rect.left,rect.top,
SRCCOPY))
{
AfxMessageBox(_T("ScreentoCompatBltFailed"));
returnFALSE;
}
//Retrievethebitmap'scolorformat,width,andheight.
if(!GetObject(hbmScreen,sizeof(BITMAP),(LPSTR)&bmp))
{
AfxMessageBox(_T("GetObject()出错!"));
returnFALSE;
}
//Convertthecolorformattoacountofbits.
cClrBits=(WORD)(bmp.bmPlanes*bmp.bmBitsPixel);
if(cClrBits==1)
cClrBits=1;
elseif(cClrBits<=4)
cClrBits=4;
elseif(cClrBits<=8)
cClrBits=8;
elseif(cClrBits<=16)
cClrBits=16;
elseif(cClrBits<=24)
cClrBits=24;
elsecClrBits=32;
//AllocatememoryfortheBITMAPINFOstructure.(Thisstructure
//containsaBITMAPINFOHEADERstructureandanarrayofRGBQUAD
//datastructures.)
if(cClrBits!=24)
pbmi=(PBITMAPINFO)LocalAlloc(LPTR,
sizeof(BITMAPINFOHEADER)+
sizeof(RGBQUAD)*(1<bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth=bmp.bmWidth;
pbmi->bmiHeader.biHeight=bmp.bmHeight;
pbmi->bmiHeader.biPlanes=bmp.bmPlanes;
pbmi->bmiHeader.biBitCount=bmp.bmBitsPixel;
if(cClrBits<24)
pbmi->bmiHeader.biClrUsed=(1<bmiHeader.biCompression=BI_RGB;
//Computethenumberofbytesinthearrayofcolor
//indicesandstoretheresultinbiSizeImage.
pbmi->bmiHeader.biSizeImage=((pbmi->bmiHeader.biWidth*cClrBits+31)&~31)/8
*pbmi->bmiHeader.biHeight;
//SetbiClrImportantto0,indicatingthatallofthedevicecolorsareimportant.
pbmi->bmiHeader.biClrImportant=0;
pbih=(PBITMAPINFOHEADER)pbmi;
lpBits=(LPBYTE)GlobalAlloc(GMEM_FIXED,pbih->biSizeImage);
if(!lpBits)
{
AfxMessageBox(_T("内存分配错误!"));
returnFALSE;
}
//Retrievethecolortable(RGBQUADarray)andthebits
//(arrayofpaletteindices)fromtheDIB.
if(!GetDIBits(hDC,hbmScreen,0,(WORD)pbih->biHeight,lpBits,pbmi,
DIB_RGB_COLORS))
{
AfxMessageBox(_T("GetDIBits()error"));
returnFALSE;
}
//Createthe.BMPfile.
hfile=CreateFile(szBMPFilename,
GENERIC_READ|GENERIC_WRITE,
(DWORD)0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
(HANDLE)NULL);
if(hfile==INVALID_HANDLE_VALUE)
{
AfxMessageBox(_T("创建文件失败"));
returnfalse;
}
hdr.bfType=0x4d42;//0x42="B"0x4d="M"
//Computethesizeoftheentirefile.
hdr.bfSize=(DWORD)(sizeof(BITMAPFILEHEADER)+
pbih->biSize+pbih->biClrUsed
*sizeof(RGBQUAD)+pbih->biSizeImage);
hdr.bfReserved1=0;
hdr.bfReserved2=0;
//Computetheoffsettothearrayofcolorindices.
hdr.bfOffBits=(DWORD)sizeof(BITMAPFILEHEADER)+
pbih->biSize+pbih->biClrUsed
*sizeof(RGBQUAD);
//CopytheBITMAPFILEHEADERintothe.BMPfile.
if(!WriteFile(hfile,(LPVOID)&hdr,sizeof(BITMAPFILEHEADER),
(LPDWORD)&dwTmp,NULL))
{
AfxMessageBox(_T("写BMP文件头失败"));
returnFALSE;
}
//CopytheBITMAPINFOHEADERandRGBQUADarrayintothefile.
if(!WriteFile(hfile,(LPVOID)pbih,sizeof(BITMAPINFOHEADER)
+pbih->biClrUsed*sizeof(RGBQUAD),
(LPDWORD)&dwTmp,(NULL)))
{
AfxMessageBox(_T("写BMP文件头失败"));
returnFALSE;
}
//Copythearrayofcolorindicesintothe.BMPfile.
cb=pbih->biSizeImage;
hp=lpBits;
if(!WriteFile(hfile,(LPSTR)hp,(int)cb,(LPDWORD)&dwTmp,NULL))
{
AfxMessageBox(_T("写入BMP文件失败"));
returnFALSE;
}
//Closethe.BMPfile.
if(!CloseHandle(hfile))
{
AfxMessageBox(_T("Can'tcloseBMPfile."));
}
//Freememory.
GlobalFree((HGLOBAL)lpBits);
//转换成PNG
if(!BMptoPNG(szBMPFilename,strFilePath))
{
DeleteFile(szBMPFilename);
returnFALSE;
}
DeleteObject(hbmScreen);
DeleteFile(szBMPFilename);
returnTRUE;
}
////转换BMP文件为PNG文件
BOOLCMakePNG::BMptoPNG(LPCWSTRStrBMp,LPCWSTRStrPNG)
{
CLSIDencoderClsid;
Statusstat;
Image*image=NULL;
image=Bitmap::FromFile(StrBMp,TRUE);
if(!GetEncoderClsid(L"image/png",&encoderClsid))
{
returnFALSE;
}
stat=image->Save(StrPNG,&encoderClsid,NULL);
if(stat!=Ok)
{
returnFALSE;
}
deleteimage;
returnTRUE;
}
//功能描述:转换PNG文件为BMP文件
BOOLCMakePNG::PNGtoBMp(LPCWSTRStrPNG,LPCWSTRStrBMp)
{
CLSIDencoderClsid;
Statusstat;
Image*pImage;
pImage=Bitmap::FromFile(StrPNG,TRUE);
if(!GetEncoderClsid(L"image/bmp",&encoderClsid))
{
returnFALSE;
}
stat=pImage->Save(StrBMp,&encoderClsid,NULL);
if(stat!=Ok)
{
returnFALSE;
}
deletepImage;
returnTRUE;
}
BOOLCMakePNG::GetEncoderClsid(WCHAR*pFormat,CLSID*pClsid)
{
UINTnum=0,size=0;
ImageCodecInfo*pImageCodecInfo=NULL;
GetImageEncodersSize(&num,&size);
if(size==0)
{
returnFALSE;
}
pImageCodecInfo=(ImageCodecInfo*)(malloc(size));
if(pImageCodecInfo==NULL)
{
returnFALSE;
}
GetImageEncoders(num,size,pImageCodecInfo);
BOOLbfound=FALSE;
for(UINTi=0;!bfound&&i
以上两个文件实际上是CMakePNG类,使用时需要把他们添加到项目中,调用方法如下:
wstringGetAppPathW()
{
wchar_tszExePath[MAX_PATH]={0};
GetModuleFileNameW(NULL,szExePath,MAX_PATH);
wchar_t*pstr=wcsrchr(szExePath,'\\');
memset(pstr+1,0,2);
wstringstrAppPath(szExePath);
returnstrAppPath;
}
//屏幕截图
CStringCDemoDlg::ScreenShot(void)
{
CWnd*pDesktop=GetDesktopWindow();
CDC*pDC=pDesktop->GetDC();
CRectrect;
//获取窗口的大小
pDesktop->GetClientRect(&rect);
//保存到的文件名
CStringstrFileName(GetAppPathW().c_str());
strFileName+=_T("ScreenShot\\");
CreateDirectory((LPCTSTR)strFileName,NULL);
CTimet=CTime::GetCurrentTime();
CStringtt=t.Format("%Y%m%d_%H%M%S");
strFileName+=tt;
strFileName+=_T(".PNG");
//保存为PNG
CMakePNGMakePNG;
MakePNG.MakePNG(pDC->m_hDC,rect,strFileName);
ReleaseDC(pDC);
returnstrFileName;
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。