C++實(shí)現(xiàn)屏幕截圖(全屏截圖)
上回分享了一個(gè)全屏截圖的代碼,保存為BMP,
C++實(shí)現(xiàn)屏幕截圖(全屏截圖):http://chabaoo.cn/article/140184.htm
實(shí)際使用的過(guò)程中我發(fā)現(xiàn)截圖文件實(shí)在大,無(wú)賴(lài)又整成了PNG截圖,現(xiàn)在分享出來(lái)。
MakePNG.h
//MakePNG.h
#pragma once
#include <GdiPlus.h>
using namespace Gdiplus;
#pragma comment(lib,"GdiPlus.lib")
class CMakePNG
{
public:
CMakePNG(void);
~CMakePNG(void);
BOOL MakePNG(HDC hDC,CRect rect,CString strFilePath);
BOOL BMptoPNG(LPCWSTR StrBMp,LPCWSTR StrPNG);
BOOL PNGtoBMp(LPCWSTR StrPNG,LPCWSTR StrBMp);
BOOL GetEncoderClsid(WCHAR* pFormat,CLSID* pClsid);
private:
GdiplusStartupInput m_gdiplusStartupInput;
ULONG_PTR m_pGdiToken;
};
MakePNG.cpp
//MakePNG.cpp
#include "StdAfx.h"
#include "MakePNG.h"
CMakePNG::CMakePNG(void)
{
GdiplusStartup(&m_pGdiToken,&m_gdiplusStartupInput,NULL);
}
CMakePNG::~CMakePNG(void)
{
}
/***************************************************************************/
/* 功能: 根據(jù)rect屏幕抓圖,保存為文件名為strFilePath的PNG圖像文件 */
/* 輸入?yún)?shù): HDC hDC 屏幕HDC; */
/* CRect rect 需要的矩形; */
/* CString strFilePath 保存文件全路徑(含后綴名); */
/***************************************************************************/
BOOL CMakePNG::MakePNG(HDC hDC, CRect rect, CString strFilePath)
{
BITMAP bmp;
PBITMAPINFO pbmi;
PBITMAPINFOHEADER pbih; // bitmap info-header
BITMAPFILEHEADER hdr; // bitmap file-header
WORD cClrBits;
LPBYTE lpBits; // memory pointer
DWORD dwTmp;
DWORD cb; // incremental count of bytes
BYTE *hp; // byte pointer
HANDLE hfile; // file handle
CString szBMPFilename = strFilePath.Left(strFilePath.GetLength() - 3) + _T("bmp");//先保存成位圖
HDC hdcCompatible = CreateCompatibleDC(hDC);
HBITMAP hbmScreen = CreateCompatibleBitmap(hDC, rect.Width(), rect.Height());
if (hbmScreen == NULL)
{
AfxMessageBox(_T("CreateCompatibleBitmap() error"));
return FALSE;
}
// Select the bitmaps into the compatible DC.
if (!SelectObject(hdcCompatible, hbmScreen))
{
AfxMessageBox(_T("Compatible Bitmap Selection error"));
return FALSE;
}
//Copy color data for the entire display into a
//bitmap that is selected into a compatible DC.
if (!BitBlt(hdcCompatible,
0,0,
rect.Width(), rect.Height(),
hDC,
rect.left,rect.top,
SRCCOPY))
{
AfxMessageBox(_T("Screen to Compat Blt Failed"));
return FALSE;
}
// Retrieve the bitmap's color format, width, and height.
if (!GetObject(hbmScreen, sizeof(BITMAP), (LPSTR)&bmp))
{
AfxMessageBox(_T("GetObject()出錯(cuò)!"));
return FALSE;
}
// Convert the color format to a count of bits.
cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
if (cClrBits == 1)
cClrBits = 1;
else if (cClrBits <= 4)
cClrBits = 4;
else if (cClrBits <= 8)
cClrBits = 8;
else if (cClrBits <= 16)
cClrBits = 16;
else if (cClrBits <= 24)
cClrBits = 24;
else cClrBits = 32;
// Allocate memory for the BITMAPINFO structure. (This structure
// contains a BITMAPINFOHEADER structure and an array of RGBQUAD
// data structures.)
if (cClrBits != 24)
pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * (1<< cClrBits));
// There is no RGBQUAD array for the 24-bit-per-pixel format.
else
pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
sizeof(BITMAPINFOHEADER));
// Initialize the fields in the BITMAPINFO structure.
pbmi->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<<cClrBits);
// If the bitmap is not compressed, set the BI_RGB flag.
pbmi->bmiHeader.biCompression = BI_RGB;
// Compute the number of bytes in the array of color
// indices and store the result in biSizeImage.
pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
* pbmi->bmiHeader.biHeight;
// Set biClrImportant to 0, indicating that all of the device colors are important.
pbmi->bmiHeader.biClrImportant = 0;
pbih = (PBITMAPINFOHEADER) pbmi;
lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
if (!lpBits)
{
AfxMessageBox(_T("內(nèi)存分配錯(cuò)誤!"));
return FALSE;
}
// Retrieve the color table (RGBQUAD array) and the bits
// (array of palette indices) from the DIB.
if (!GetDIBits(hDC, hbmScreen, 0, (WORD) pbih->biHeight, lpBits, pbmi,
DIB_RGB_COLORS))
{
AfxMessageBox(_T("GetDIBits() error"));
return FALSE;
}
// Create the .BMP file.
hfile = CreateFile(szBMPFilename,
GENERIC_READ | GENERIC_WRITE,
(DWORD) 0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
if (hfile == INVALID_HANDLE_VALUE)
{
AfxMessageBox(_T("創(chuàng)建文件失敗"));
return false;
}
hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M"
// Compute the size of the entire file.
hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) +
pbih->biSize + pbih->biClrUsed
* sizeof(RGBQUAD) + pbih->biSizeImage);
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
// Compute the offset to the array of color indices.
hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) +
pbih->biSize + pbih->biClrUsed
* sizeof (RGBQUAD);
// Copy the BITMAPFILEHEADER into the .BMP file.
if (!WriteFile(hfile, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER),
(LPDWORD) &dwTmp, NULL))
{
AfxMessageBox(_T("寫(xiě)B(tài)MP文件頭失敗"));
return FALSE;
}
// Copy the BITMAPINFOHEADER and RGBQUAD array into the file.
if (!WriteFile(hfile, (LPVOID) pbih, sizeof(BITMAPINFOHEADER)
+ pbih->biClrUsed * sizeof (RGBQUAD),
(LPDWORD) &dwTmp, ( NULL)))
{
AfxMessageBox(_T("寫(xiě)B(tài)MP文件頭失敗"));
return FALSE;
}
// Copy the array of color indices into the .BMP file.
cb = pbih->biSizeImage;
hp = lpBits;
if (!WriteFile(hfile, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL))
{
AfxMessageBox(_T("寫(xiě)入BMP文件失敗"));
return FALSE;
}
// Close the .BMP file.
if (!CloseHandle(hfile))
{
AfxMessageBox(_T("Can't close BMP file."));
}
// Free memory.
GlobalFree((HGLOBAL)lpBits);
//轉(zhuǎn)換成PNG
if(!BMptoPNG(szBMPFilename,strFilePath))
{
DeleteFile(szBMPFilename);
return FALSE;
}
DeleteObject(hbmScreen);
DeleteFile(szBMPFilename);
return TRUE;
}
// //轉(zhuǎn)換BMP文件為PNG文件
BOOL CMakePNG::BMptoPNG(LPCWSTR StrBMp,LPCWSTR StrPNG)
{
CLSID encoderClsid;
Status stat;
Image* image = NULL;
image = Bitmap::FromFile(StrBMp,TRUE);
if (!GetEncoderClsid(L"image/png",&encoderClsid))
{
return FALSE;
}
stat = image->Save(StrPNG,&encoderClsid,NULL);
if (stat != Ok)
{
return FALSE;
}
delete image;
return TRUE;
}
// 功能描述: 轉(zhuǎn)換PNG文件為BMP文件
BOOL CMakePNG::PNGtoBMp(LPCWSTR StrPNG,LPCWSTR StrBMp)
{
CLSID encoderClsid;
Status stat;
Image* pImage;
pImage = Bitmap::FromFile(StrPNG,TRUE);
if (!GetEncoderClsid(L"image/bmp",&encoderClsid))
{
return FALSE;
}
stat = pImage->Save(StrBMp,&encoderClsid,NULL);
if (stat != Ok)
{
return FALSE;
}
delete pImage;
return TRUE;
}
BOOL CMakePNG::GetEncoderClsid(WCHAR* pFormat,CLSID* pClsid)
{
UINT num = 0,size = 0;
ImageCodecInfo* pImageCodecInfo = NULL;
GetImageEncodersSize(&num,&size);
if (size == 0)
{
return FALSE;
}
pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if (pImageCodecInfo == NULL)
{
return FALSE;
}
GetImageEncoders(num,size,pImageCodecInfo);
BOOL bfound = FALSE;
for (UINT i = 0;!bfound && i < num; i++)
{
if (_wcsicmp(pImageCodecInfo[i].MimeType,pFormat) == 0)
{
*pClsid = pImageCodecInfo[i].Clsid;
bfound = TRUE;
}
}
free(pImageCodecInfo);
return bfound;
}
以上兩個(gè)文件實(shí)際上是CMakePNG類(lèi),使用時(shí)需要把他們添加到項(xiàng)目中,調(diào)用方法如下:
wstring GetAppPathW()
{
wchar_t szExePath[MAX_PATH] = {0};
GetModuleFileNameW(NULL, szExePath, MAX_PATH);
wchar_t *pstr = wcsrchr(szExePath, '\\');
memset(pstr + 1, 0, 2);
wstring strAppPath(szExePath);
return strAppPath;
}
// 屏幕截圖
CString CDemoDlg::ScreenShot(void)
{
CWnd *pDesktop = GetDesktopWindow();
CDC *pDC = pDesktop->GetDC();
CRect rect;
//獲取窗口的大小
pDesktop->GetClientRect(&rect);
//保存到的文件名
CString strFileName(GetAppPathW().c_str());
strFileName += _T("ScreenShot\\");
CreateDirectory((LPCTSTR)strFileName,NULL);
CTime t = CTime::GetCurrentTime();
CString tt = t.Format("%Y%m%d_%H%M%S");
strFileName += tt;
strFileName += _T(".PNG");
//保存為PNG
CMakePNG MakePNG;
MakePNG.MakePNG(pDC->m_hDC,rect,strFileName);
ReleaseDC(pDC);
return strFileName;
}
到此這篇關(guān)于C++實(shí)現(xiàn)屏幕截圖(全屏截圖)的文章就介紹到這了,更多相關(guān)C++ 屏幕截圖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Matlab中圖像數(shù)字水印算法的原理與實(shí)現(xiàn)詳解
數(shù)字水印技術(shù)作為信息隱藏技術(shù)的一個(gè)重要分支,是將信息(水印)隱藏于數(shù)字圖像、視頻、音頻及文本文檔等數(shù)字媒體中,從而實(shí)現(xiàn)隱秘傳輸、存儲(chǔ)、標(biāo)注、身份識(shí)別、版權(quán)保護(hù)和防篡改等目的。本文就來(lái)講講圖像數(shù)字水印算法的原理與實(shí)現(xiàn),感興趣的可以了解一下2023-04-04
基于opencv實(shí)現(xiàn)視頻中的顏色識(shí)別功能
這篇文章主要介紹了基于opencv實(shí)現(xiàn)視頻中的顏色識(shí)別功能,文章詳細(xì)介紹了顏色識(shí)別的原理及opencv中的顏色模型,基于c++代碼實(shí)現(xiàn)顏色識(shí)別功能,需要的朋友可以參考下2022-07-07
C++17 使用 std::string_view避免字符串拷貝優(yōu)化程序性能
這篇文章主要介紹了C++17 使用 std::string_view避免字符串拷貝優(yōu)化程序性能,幫助大家提高程序運(yùn)行速度,感興趣的朋友可以了解下2020-10-10
C++實(shí)現(xiàn)十大排序算法及排序算法常見(jiàn)問(wèn)題
法是程序的靈魂,無(wú)論學(xué)習(xí)什么語(yǔ)言,做什么工程項(xiàng)目,都要考慮算法的效率實(shí)現(xiàn),下面這篇文章主要給大家介紹了關(guān)于C++實(shí)現(xiàn)十大排序算法及排序算法常見(jiàn)問(wèn)題的相關(guān)資料,需要的朋友可以參考下2021-09-09
VC運(yùn)用OPENGL加載BMP紋理圖的實(shí)現(xiàn)方法匯總
這篇文章主要介紹了VC運(yùn)用OPENGL加載BMP紋理圖的實(shí)現(xiàn)方法,對(duì)于更好的了解OpenGL很有幫助,需要的朋友可以參考下2014-07-07
C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單貪吃蛇小游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單貪吃蛇小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-09-09
C++數(shù)據(jù)結(jié)構(gòu)之搜索二叉樹(shù)的實(shí)現(xiàn)
了解搜索二叉樹(shù)是為了STL中的map和set做鋪墊,我們所熟知的AVL樹(shù)和平衡搜索二叉樹(shù)也需要搜索二叉樹(shù)的基礎(chǔ)。本文將詳解如何利用C++實(shí)現(xiàn)搜索二叉樹(shù),需要的可以參考一下2022-05-05

