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; }以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。