使用GDI+ 保存HDC为位图文件

//GDI+为图片的加载、存储,屏蔽了内部编解码、压缩解压缩等的具体细节,给程序员带来了极大的方便  
//目前版本的GDI+支持bmp jpeg gif tiff png等几种格式  
//下面的程序基本思路是先将目标DC上的内容存到内存BITMAP  
//再使用GDI+Bitmap::FromHBITMAP加载内存位图,并保存成文件  
//此版本在Win32和MFC环境下测试通过  
//  
//使用GDI+ 保存HDC为位图文件  
  
#include <rpc.h>  
#include <rpcndr.h>  
#include <unknwn.h>  
#include <gdiplus.h>  
using namespace Gdiplus;  
#pragma comment(lib, "gdiplus.lib")  
  
struct _GdiplusToken  
{  
  Gdiplus::GdiplusStartupInput gdiplusStartupInput;  
  ULONG_PTR gdiplusToken;  
  
  _GdiplusToken()  
  {  
    if(Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) != Ok)  
    {  
      MessageBox(NULL, _T("GdiplusStartup failed"), _T("Error"), MB_OK);  
    }  
  }  
  
  ~_GdiplusToken()  
  {  
    Gdiplus::GdiplusShutdown(gdiplusToken);  
  }    
}GdiplusToken;  
  
  
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;  
  
  Gdiplus::GetImageEncodersSize(&num, &size);  
  if(size == 0)  
    return -1;  // Failure  
  
  pImageCodecInfo = (ImageCodecInfo*)(malloc(size));  
  if(pImageCodecInfo == NULL)  
    return -1;  // Failure  
  
  Gdiplus::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 SaveHDCToFile(HDC hDC, LPRECT lpRect)  
{     
  BOOL bRet = FALSE;  
  int nWidth = lpRect->right - lpRect->left;  
  int nHeight = lpRect->bottom - lpRect->top;  
  
  //将目标区域贴图到内存BITMAP  
  HDC memDC = CreateCompatibleDC(hDC);   
  HBITMAP hBmp = CreateCompatibleBitmap(hDC, nWidth, nHeight);  
  SelectObject(memDC, hBmp);  
  BitBlt(memDC, lpRect->left, lpRect->top, nWidth, nHeight,  
    hDC, 0, 0, SRCCOPY);  
  
  //保存成文件  
  {  
    //L"image/bmp" L"image/jpeg"  L"image/gif" L"image/tiff" L"image/png"  
    CLSID pngClsid;  
    GetEncoderClsid(L"image/bmp", &pngClsid);//此处以BMP为例,其它格式选择对应的类型,如JPG用L"image/jpeg"   
  
    Gdiplus::Bitmap *pbmSrc = Gdiplus::Bitmap::FromHBITMAP(hBmp, NULL);  
    if( pbmSrc->Save(L"C:\\test.bmp", &pngClsid) == Ok)  
    {  
      bRet = TRUE;  
    }  
    delete pbmSrc;  
  }  
  
  //清理工作  
  SelectObject(memDC, (HBITMAP)NULL);  
  DeleteDC(memDC);    
  DeleteObject(hBmp);  
  
  return bRet;  
}  

 
 
[cpp] view plaincopy
//Win32下的测试用例  
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  
{  
  int wmId, wmEvent;  
  PAINTSTRUCT ps;  
  HDC hdc;  
  
  switch (message)  
  {  
  case WM_PAINT:  
    hdc = BeginPaint(hWnd, &ps);  
    // TODO: 在此添加任意绘图代码...  
    TextOut(hdc, 0, 0, _T("ABCD"), 4);  
    EndPaint(hWnd, &ps);  
    break;  
  case WM_KEYDOWN:  
    {  
      HDC hDC = GetDC(hWnd);  
      RECT rcRect;  
      GetClientRect(hWnd, &rcRect);  
      SaveHDCToFile(hDC, &rcRect);  
      ReleaseDC(hWnd, hDC);  
      break;  
    }   
  case WM_DESTROY:  
    PostQuitMessage(0);  
    break;  
  default:  
    return DefWindowProc(hWnd, message, wParam, lParam);  
  }  
  return 0;  
}  
原文地址:https://www.cnblogs.com/wangjixianyun/p/2876929.html