在stdafx.h文件中定义
#ifndef _UNICODE
#define _UNICODE
#endif
#ifndef UNICODE
#define UNICODE
#endif
#pragma comment(lib,"gdiplus.lib")
#include
using namespace Gdiplus;
//如果原项目为非UNICODE编码环境,那么修改项目为UNICODE编码环境的方法为:
//在项目属性对话框的链接器->高级->入口点中设置值为wWinMainCRTStartup。
在*.cpp文件中
#include "stdafx.h"
//通过GDI方法进行屏幕抓图,用GDI+方法保存Bitmap文件
#define USE_GDI_GDIPLUS_STORE_BMP
////通过GDI方法进行屏幕抓图和保存Bitmap文件
//#define USE_GDI_STORE_BMP
//将Bitmap文件保存在Windows的剪贴版中
#define STORE_IN_CLIPBOARD
//@brief 用GDI+的方法将Bitmap图片保存为文件
//@date 1-13-2009
//@param [in] hBitmap hBitmap的句柄(handle)
//@param [in] lpszFileName 保存图片的完整路径
//@return 成功返回TRUE,失败返回FALSE
BOOL C**Dlg::GDIPlus_SaveBitmapToFile(HBITMAP hBitmap, LPCTSTR lpszFileName)
{
CLSID pngClsid;
Bitmap bmp(hBitmap,NULL);
//获取BMP文件的编码方式(如果希望获取JPEG的编码方式,
//那么参数一要设置为:_TEXT("image/jpeg"),其他支持的图片格式类似)
int nResult = GetEncoderClsid(_TEXT("image/bmp"),&pngClsid);
if(nResult >= 0)
{
//保存所截取的屏幕图片
bmp.Save(lpszFileName,&pngClsid);
}
else
{
return FALSE;
}
return TRUE;
}
//@brief 获取图片文件的编码方式,支持bmp、jpg、jpeg、gif、tiff和png等格式图片
//@date 1-13-2009
//@param [in] format 图片格式 值可以为以下几种
//@"image/bmp"
//@"image/jpeg"
//@"image/gif"
//@"image/tiff"
//@"image/png"
//@param [in] pClsid
//@return 成功则返回值 >= 0,失败则返回值为-1
int C**Dlg::GetEncoderClsid(const WCHAR* format, CLSID *pClsid)
{
int nRet = -1;
ImageCodecInfo* pCodecInfo = NULL;
UINT nNum = 0,nSize = 0;
GetImageEncodersSize(&nNum,&nSize);
if (nSize<0)
{
return nRet;
}
pCodecInfo= new ImageCodecInfo[nSize];
if (pCodecInfo==NULL)
{
return nRet;
}
GetImageEncoders(nNum,nSize,pCodecInfo);
for (UINT i=0; i
if (wcscmp(pCodecInfo[i].MimeType,format)==0)
{
*pClsid= pCodecInfo[i].Clsid;
nRet = i;
delete[] pCodecInfo;
return nRet;
}
else
{
continue;
}
}
delete[] pCodecInfo;
return nRet;
}
//@brief 用GDI+的方法将两个图片(strSrcImage1,strSrcImage2)组合成一个strDestImage
//@date 1-13-2009
//@param [in] format 图片格式 值可以为以下几种
//@"image/bmp"
//@"image/jpeg"
//@"image/gif"
//@"image/tiff"
//@"image/png"
//@param [in] strDestImage表示目的图片路径
//@param [in] strSrcImage1表示源图片路径1
//@param [in] strSrcImage2表示源图片路径2
//@return TRUE表示合成图片成功,FALSE表示合成图片失败
BOOL C**Dlg::GDIPlus_CombineImage(const WCHAR *format, WCHAR* strDestImage,\
WCHAR* strSrcImage1,WCHAR* strSrcImage2)
{
BOOL bCombine = FALSE;
int nRet = 0;
CLSID clsid;
nRet= GetEncoderClsid(format,&clsid);
if (nRet >= 0)
{
Bitmap srcbmp1(strSrcImage1);
Bitmap srcbmp2(strSrcImage2);
int nWidth = 0, nHeight = 0;
nWidth = srcbmp1.GetWidth();
nHeight= srcbmp1.GetHeight();
//高不变,宽*2,水平合并
Bitmap bmpCombine(2*nWidth,nHeight);
Graphics * pG = NULL;
pGraphics = Graphics::FromImage(&bmpCombine);
if (pGraphics!=NULL)
{
//将srcbmp1画到画布pGraphics上
pGraphics->DrawImage(&srcbmp1,0,0);
//将srcbmp2画到画布pGraphics上
pGraphics->DrawImage(&srcbmp2,nWidth,0);
//保存图片bmpCombine到路径strDestImage
bmpCombine.Save(strDestImage,&clsid,NULL);
bCombine = TRUE;
}
}
return bCombine;
}
//@brief 用GDI的方法将Bitmap图片保存为文件
//@date 1-13-2009
//@param [in] hDC DC设备的句柄
//@param [in] bitmap 被保存的Bitmap图片
//@param [in] lpszFileName 被保存Bitmap图片的完整路径
//@return 返回TRUE表示保存图片成功,FALSE表示保存图片失败
BOOL C**Dlg::GDI_SaveBitmapToFile(HDC hDC, CBitmap &bitmap, LPCTSTR lpszFileName)
{
BOOL ret = TRUE;
BITMAP btm;
bitmap.GetBitmap(&btm);
DWORD size = btm.bmWidthBytes * btm.bmHeight;
//接下来要使用GlobalAlloc()函数从堆中分配指定大小的内存,并返回指向这块内存的指针,
//分配内存是将内存的内容初始化为全零。
HGLOBAL hMem = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,size);
if(hMem == NULL)
{
return FALSE;
}
//为了保护我们分配的这块内存,我们要调用GlobalLock来锁定这块内存,
//避免被其他的进程占用,这个函数返回指向内存锁的第一个指针
LPSTR lpData = (LPSTR)GlobalLock(hMem);
//定义位图头,并对这个结构体变量初始化,这个结构之后初始化之后才能使用,
//尤其要指定位图的大小和位图的高度宽度
BITMAPINFOHEADER bih;
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biWidth = btm.bmWidth;
bih.biHeight = btm.bmHeight;
bih.biPlanes = 1;
bih.biBitCount = btm.bmBitsPixel;
bih.biCompression = 0;
bih.biSizeImage = size;
bih.biXPelsPerMeter = 0;
bih.biYPelsPerMeter = 0;
bih.biClrUsed = 0;
bih.biClrImportant = 0;
//将位图中的数据以bits的形式放入lpData指向的位图数组中,这里用到了GetDIBits()函数。
if(GetDIBits(hDC,bitmap,0,bih.biHeight,lpData,(BITMAPINFO*)&bih,DIB_RGB_COLORS) == 0)
{
GlobalFree(hMem);
return FALSE;
}
int iRes = GetDeviceCaps(hDC, SIZEPALETTE);
long plSize = iRes * sizeof(RGBQUAD);
//位图文件和普通的文件使用起来有区别,为了保存位图,我们这里定义了一个位图文件,
//用它来专门保存位图文件,在使用之前,也要填充位图文件的头部信息。Bfh的bfType成员没有选择,
//必须赋值为BM,bfReserved1和bfReserved2都必须指定为0。
BITMAPFILEHEADER bfh;
bfh.bfType = ((WORD)('M'<< 8)|'B') ;//BM
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfSize = sizeof(bfh)+size;
bfh.bfOffBits = plSize + sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER);
CFile bf;
//对于位图文件的写入,我们可以使用下面的方法
if(bf.Open(lpszFileName, CFile::modeCreate|CFile::modeWrite))
{
bf.Write(&bfh,sizeof(BITMAPFILEHEADER));
bf.Write(&bih,sizeof(BITMAPINFOHEADER));
bf.Write(lpData,size);
bf.Close();
}
else
{
ret = FALSE;
}
//释放掉从堆中分配的内存,避免内存泄露
GlobalFree(hMem);
return ret;
}
//@brief 用GDI的方法将两张Bitmap图片合并起来
//@date 1-13-2009
//@param [in] pDC DC设备
//@param [in] pBitmap1 被合并的Bitmap图片1
//@param [in] pBitmap2 被合并的Bitmap图片2
//@return void
void C**Dlg::GDI_CombineBitmap(CDC *pDC, CBitmap *pBitmap1, CBitmap *pBitmap2)
{
CDC m_dcBk; ///<绘制背景图设备
CDC m_dcFore; ///<绘制前景图设备
CClientDC dc(this); //获得当前客户区设备环境
m_dcBk.CreateCompatibleDC(&dc); //创建与当前设备相兼容的设备
m_dcFore.CreateCompatibleDC(&dc);
CBitmap *poldBk = m_dcBk.SelectObject(pBitmap1); //选入背景图
CBitmap *poldFore = m_dcFore.SelectObject(pBitmap2);
CRect rect;
CListCtrl m_NavigationList; ///<列表型控件变量
m_NavigationList.GetClientRect(&rect); //得到客户区矩形
CDC maskDc; //创建设备环境maskDc
maskDc.CreateCompatibleDC(pDC); //创建与当前设备相兼容的设备
CBitmap maskBitmap;
maskBitmap.CreateBitmap(rect.Width(), rect.Height(), 1, 1, NULL ); //创建一个单色图
CBitmap* pOldMaskDCBitmap = maskDc.SelectObject( &maskBitmap ); //选入单色图
CBrush brush(RGB(255,255,255));
CBrush * oldbrush = NULL;
oldbrush = maskDc.SelectObject(&brush);
maskDc.FillRect(&rect,&brush);
//取得要消除的背景色值
COLORREF clrTrans = m_dcFore.GetPixel(2, 2);
//设置前景图的背景色
COLORREF clrSaveBk = m_dcFore.SetBkColor(clrTrans);
//将前景图拷贝到maskDc
maskDc.BitBlt(0,0,rect.Width(),rect.Height(), &m_dcFore, 0,0,SRCCOPY);
//前景图与mask做‘与’运算
m_dcFore.SetBkColor(RGB(0,0,0));
m_dcFore.SetTextColor(RGB(255,255,255));
m_dcFore.BitBlt(0,0,rect.Width(), rect.Height(),&maskDc,0,0,SRCAND);
//背景图与mask做‘与’运算
m_dcBk.SetBkColor(RGB(255,255,255));
m_dcBk.SetTextColor(RGB(0,0,0));
m_dcBk.BitBlt(0,0,rect.Width(),rect.Height(),&maskDc,0,0,SRCAND);
//背景图与前景图做‘或’运算
m_dcBk.BitBlt(rect.left,rect.top,rect.Width(),rect.Height(),&m_dcFore,0,0,SRCPAINT);
////将合成后的图像显示出来
//pDC->BitBlt(0,0,rect.Width(),rect.Height(),&m_dcBk,0,0,SRCCOPY);
pDC->SelectObject(oldbrush);
m_dcBk.SelectObject(poldBk);
m_dcFore.SelectObject(poldFore);
}
//@brief 实现屏幕抓图功能,并将抓取的图片保存为Bitmap文件
//@date 1-12-2009
//@return 返回TRUE表示操作成功
BOOL C**Dlg::GetScreenBmpImage()
{
#ifdef USE_GDI_STORE_BMP
//定义源图片(屏幕抓图)的Left、Top、Width和Height
int nSrcImageLeft = 200;
int nSrcImageTop = 200;
int nSrcImageWidth = 0;
int nSrcImageHeight = 0;
//获取源图片(屏幕抓图)Bitmap的宽高
nSrcImageWidth = GetSystemMetrics(SM_CXSCREEN);
nSrcImageHeight= GetSystemMetrics(SM_CYSCREEN);
//定义被保存的图片的Left、Top、Width和Height
int nDestImageLeft = 0;
int nDestImageTop = 0;
int nDestImageWidth = 500;
int nDestImageHeight = 500;
CDC dc;
//获取整个屏幕的dc(设备场景)
dc.CreateDC(_TEXT("DISPLAY"),NULL,NULL,NULL);
//为屏幕dc创建兼容的内存dcMem
CDC dcMem;
dcMem.CreateCompatibleDC(&dc);
//创建一个与屏幕dc兼容的位图
CBitmap bitmap;
bitmap.CreateCompatibleBitmap(&dc, nSrcImageWidth, nSrcImageHeight);
//把新位图选到内存dc中,并保存原位图
CBitmap *pOldBitmap = dcMem.SelectObject(&bitmap);
//将屏幕图像从屏幕dc拷到内存dc,其实拷到到bitmap中
dcMem.BitBlt(nDestImageLeft,nDestImageTop,nDestImageWidth,nDestImageHeight,&dc,
nSrcImageLeft,nSrcImageTop,SRCCOPY);
//恢复内存dc中的原位图
dcMem.SelectObject(pOldBitmap);
WCHAR strFileFullPath[MAX_PATH] = {0};
wcscpy(strFileFullPath,_TEXT("c:\\GDI_Screen.bmp"));
this->GDI_SaveBitmapToFile(dc.GetSafeHdc(), bitmap, strFileFullPath);
dc.DeleteDC();
#endif
#ifdef USE_GDI_GDIPLUS_STORE_BMP
//定义源图片(屏幕抓图)的Left、Top、Width和Height
int nSrcImageLeft = 200;
int nSrcImageTop = 200;
int nSrcImageWidth = 0;
int nSrcImageHeight = 0;
//获取源图片(屏幕抓图)Bitmap的宽高
nSrcImageWidth = GetSystemMetrics(SM_CXSCREEN);
nSrcImageHeight= GetSystemMetrics(SM_CYSCREEN);
//定义被保存的图片的Left、Top、Width和Height
int nDestImageLeft = 0;
int nDestImageTop = 0;
int nDestImageWidth = 400;
int nDestImageHeight = 500;
HDC hdcScreen,hMemDC;
HBITMAP hBitmap,hOldBitmap;
//建立一个屏幕设备环境句柄
hdcScreen = CreateDC(_TEXT("DISPLAY"),NULL,NULL,NULL);
//建立一个与屏幕设备环境句柄兼容的内存DC
hMemDC = CreateCompatibleDC(hdcScreen);
//建立一个与屏幕设备环境句柄兼容、宽高为nSrcImageWidth,nSrcImageHeight的画布,用于将各个图像添加上去
hBitmap = CreateCompatibleBitmap(hdcScreen,nSrcImageWidth,nSrcImageHeight);
//把新位图选到内存设备描述表中
hOldBitmap = (HBITMAP)SelectObject(hMemDC,hBitmap);
//把屏幕设备描述表拷贝到内存设备描述表中
BitBlt(hMemDC,nDestImageLeft,nDestImageTop,nDestImageWidth,nDestImageHeight,
hdcScreen,nSrcImageLeft,nSrcImageTop,SRCCOPY);
nDestImageLeft = 500;
nDestImageTop = 500;
nDestImageWidth = 600;
nDestImageHeight = 700;
nSrcImageLeft = 500;
nSrcImageTop = 500;
//把屏幕设备描述表拷贝到内存设备描述表中
BitBlt(hMemDC,nDestImageLeft,nDestImageTop,nDestImageWidth,
nDestImageHeight,hdcScreen,nSrcImageLeft,nSrcImageTop,SRCCOPY);
DeleteDC(hdcScreen);
DeleteDC(hMemDC);
WCHAR strFileFullPath[MAX_PATH] = {0};
wcscpy(strFileFullPath,_TEXT("c:\\GDIPlus_Screen.bmp"));
//保存的图片大小由hBitmap的nSrcImageWidth和nSrcImageHeight决定
this->GDIPlus_SaveBitmapToFile(hBitmap, strFileFullPath);
#else
//定义源图片(屏幕抓图)的Left、Top、Width和Height
int nSrcImageLeft = 0;
int nSrcImageTop = 0;
int nSrcImageWidth = 0;
int nSrcImageHeight = 0;
//获取源图片(屏幕抓图)Bitmap的宽高
nSrcImageWidth = GetSystemMetrics(SM_CXSCREEN);
nSrcImageHeight= GetSystemMetrics(SM_CYSCREEN);
//定义被保存的图片的Left、Top、Width和Height
int nDestImageLeft = 0;
int nDestImageTop = 0;
int nDestImageWidth = GetSystemMetrics(SM_CXSCREEN);
int nDestImageHeight = GetSystemMetrics(SM_CYSCREEN);
CDC dc;
HDC hScreenBmpDC;
//获取整个屏幕的dc(设备场景)
dc.CreateDC(_TEXT("DISPLAY"),NULL,NULL,NULL);
Graphics ScreenGraghics(dc.m_hDC) ;
//创建以屏幕大小为标准的位图
Bitmap SrcBitmap1(nSrcImageWidth , nSrcImageHeight , &ScreenGraghics ) ;
this->GDIPlus_GetBitmap(nDestImageLeft,nDestImageTop,nDestImageWidth,nDestImageHeight);
//Image是Bitmap的父类
Graphics* DestBitmapGraphics = Graphics::FromImage( &SrcBitmap1 ) ;
hScreenBmpDC = ScreenGraghics.GetHDC();
HDC hDestBmpDC = DestBitmapGraphics->GetHDC();
BitBlt ( hDestBmpDC , nDestImageLeft , nDestImageTop , nDestImageWidth ,
nDestImageHeight , hScreenBmpDC , nSrcImageLeft , nSrcImageTop , SRCCOPY ) ;
//释放Bitmap的DC
DestBitmapGraphics->ReleaseHDC( hDestBmpDC ) ;
//释放屏幕的DC
ScreenGraghics.ReleaseHDC(hScreenBmpDC);
//获取整个屏幕的dc(设备场景)
dc.CreateDC(_TEXT("DISPLAY"),NULL,NULL,NULL);
Graphics ScreenGraghics2(dc.m_hDC) ;
//定义被保存的图片的Left、Top、Width和Height
nDestImageLeft = 0;
nDestImageTop = 0;
nDestImageWidth = 1280;
nDestImageHeight = 1024;
//创建以屏幕大小为标准的位图
Bitmap SrcBitmap2(nSrcImageWidth , nSrcImageHeight , &ScreenGraghics2 ) ;
//Image是Bitmap的父类
Graphics* DestBitmapGraphics2 = Graphics::FromImage( &SrcBitmap2 ) ;
hScreenBmpDC = ScreenGraghics2.GetHDC();
HDC hDestBmpDC2 = DestBitmapGraphics2->GetHDC();
BitBlt ( hDestBmpDC2 , nDestImageLeft , nDestImageTop ,nDestImageWidth ,
nDestImageHeight ,hScreenBmpDC , nSrcImageLeft , nSrcImageTop , SRCCOPY ) ;
//释放Bitmap的DC
DestBitmapGraphics2->ReleaseHDC( hDestBmpDC2 ) ;
//释放屏幕的DC
ScreenGraghics2.ReleaseHDC(hScreenBmpDC);
int nbmpCombineWidth = GetSystemMetrics(SM_CXSCREEN);
int nbmpCombineHeight= GetSystemMetrics(SM_CYSCREEN);
//用于Bitmap合并的画布
Bitmap bmpCombine(2*nbmpCombineWidth,nbmpCombineHeight);
Graphics * pG = NULL;
pG = Graphics::FromImage(&bmpCombine);
if (pG != NULL)
{
pG->DrawImage(&SrcBitmap1,0,0,1280,1024);
pG->DrawImage(&SrcBitmap2,500,0,1280,1024);
CLSID pngClsid;
//获取BMP文件的编码方式
int nResult = GetEncoderClsid(_TEXT("image/bmp"),&pngClsid);
bmpCombine.Save(_TEXT("c:\\Capture2.bmp"),&pngClsid,NULL);
}
#endif
#ifdef STORE_IN_CLIPBOARD
//屏幕已拷到兼容位图bitmap上,下面将它保存到剪贴板
if((::OpenClipboard(NULL) != 0) && (::EmptyClipboard() != 0))
{
::SetClipboardData(CF_BITMAP,bitmap.GetSafeHandle());
::CloseClipboard();
}
#endif
return TRUE;
}
//@brief 创建一个画布,在上面任意画图形,并且返回该画布的缩略图
//@date 1-13-2009
//@return 返回缩略图指针
Bitmap * C**Dlg::GetThumbnailPageImage()
{
int nScreenWidth = ::GetSystemMetrics(SM_CXSCREEN);
int nScreenHeight = ::GetSystemMetrics(SM_CYSCREEN);
//定义宽为nScreenWidth,高为nScreenHeight的位图
Bitmap pPageImage(nScreenWidth, nScreenHeight, PixelFormat16bppRGB565);
//Imagegraphics作为pPageImage的画布,接受绘画的信息
Graphics Imagegraphics(&pPageImage);
SolidBrush bkbrush(Color(255,255,255,0));
//填充画布背景Imagegraphics
Imagegraphics.FillRectangle(&bkbrush, 0, 0, nScreenWidth, nScreenHeight);
Pen pen(Color(255,255,0,0), 4.0f);
//在画布上画个矩形
Imagegraphics.DrawRectangle(&pen, 200, 200, 500, 500);
////在画布上画图形(这是GDI+合并图片的方法之一)
//Imagegraphics.DrawImage()
//缩略图的宽
int nThumbnailWidth = 90;
//缩略图的高
int nThumbnailHeight = 90;
Bitmap *pThumbnailImage = NULL;
//获取Bitmap(pPageImage)的缩略图
pThumbnailImage = (Bitmap *)pPageImage.GetThumbnailImage(nThumbnailWidth, nThumbnailHeight,NULL, NULL);
//返回缩略图指针
return pThumbnailImage;
}