Home > Win32/MFC > Simple code to create an EMF or Bitmap file from existed draw code

Simple code to create an EMF or Bitmap file from existed draw code

December 16th, 2006

We often need to create an Enhanced Meta File(EMF) or Bitmap(bmp) from an existed DC draw code. It’s not very difficult but it’s boring to code again and again.
The following is a simple solution, what you need to do is only to implement an IPicDrawer and call DrawEnhMeta or DrawBitmap function.


download: demo_src.cpp
struct IPicDrawer
{
 
virtual void GetSize(CSize&) = 0; // It's the smallest size for EMF
 
virtual BOOL Draw(CDC*) = 0;
};
 
BOOL DrawEnhMeta(LPCTSTR lpszFileName, IPicDrawer *pIDrawer)
{
 
// Draw EMF file, the limitation of DC function refer to MSDN
 
HDC hDC = ::CreateEnhMetaFile(NULL, lpszFileName, NULL,
      
_T("FQ EMF Func\0No Title\0"));
 
CDC *pDC = CDC::FromHandle(hDC);
 
if(pDC)
 
{
    
CSize sz;
    
pIDrawer->GetSize(sz);
    
pDC->FillRect(CRect(0,0,sz.cx,sz.cy), &CBrush(RGB(255,255,255)));
    
if(pIDrawer->Draw(pDC))
    
{
      
HENHMETAFILE hEmf = ::CloseEnhMetaFile(hDC);
      
if(hEmf)
      
{
        ::
DeleteEnhMetaFile(hEmf);
        
return TRUE;
      
}
      
else
        ::
DeleteFile(lpszFileName);
    
}
 
}
 
return FALSE;
}
 
BOOL DrawBitmap(LPCTSTR lpszFileName, IPicDrawer *pIDrawer)
{
 
// Draw 24 bit true color bitmap file
 
HANDLE hFile = ::CreateFile(lpszFileName, GENERIC_READ | GENERIC_WRITE,
    
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
 
BOOL bRet = FALSE;
 
if(hFile)
 
{
    
CSize sz;
    
pIDrawer->GetSize(sz);
    
BITMAPINFO BmpInfo = {0, }; //
    
BmpInfo.bmiHeader.biWidth = sz.cx;
    
BmpInfo.bmiHeader.biHeight = sz.cy;
    
BmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    
BmpInfo.bmiHeader.biPlanes = 1;
    
BmpInfo.bmiHeader.biBitCount = 24; // 24bit
    
BmpInfo.bmiHeader.biCompression = BI_RGB;
    
BmpInfo.bmiHeader.biSizeImage = BmpInfo.bmiHeader.biBitCount / 8 *
      
BmpInfo.bmiHeader.biWidth * BmpInfo.bmiHeader.biHeight;
 
    
BITMAPFILEHEADER bmpFileHeader = {0, }; //
    
bmpFileHeader.bfType = *(WORD*)_T("BM");
    
bmpFileHeader.bfOffBits =
      
sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    
bmpFileHeader.bfOffBits +=
      
sizeof(DWORD) - (bmpFileHeader.bfOffBits % sizeof(DWORD));
    
bmpFileHeader.bfSize = bmpFileHeader.bfOffBits + BmpInfo.bmiHeader.biSizeImage;
    
//write file header and image information
    
DWORD dwNum = 0;
    
bRet = ::WriteFile(hFile, &bmpFileHeader, sizeof(BITMAPFILEHEADER),
      &
dwNum, NULL);
    
bRet = bRet && ::WriteFile(hFile, &(BmpInfo.bmiHeader), sizeof(BITMAPINFOHEADER),
      &
dwNum, NULL);
    
if(bRet)
    
{
      
bRet = FALSE;
      
//create file mapping
      
HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READWRITE,
        
0, bmpFileHeader.bfSize, NULL);
      
if(hMap)
      
{
        
// create bitmap object
        
void *pBits = NULL;
        
HBITMAP hBMP = ::CreateDIBSection(NULL, &BmpInfo, DIB_RGB_COLORS,
          &
pBits, hMap, bmpFileHeader.bfOffBits);
        
if(hBMP)
        
{
          
// draw the specified figure to file
          
CDC memTmpDC;
          
memTmpDC.CreateCompatibleDC(NULL);
          
if(memTmpDC.GetSafeHdc())
          
{
            
CBitmap *pbmp;
            
pbmp = CBitmap::FromHandle(hBMP);
            
if(pbmp)
            
{
              
memTmpDC.SelectObject(pbmp);
              
memTmpDC.FillRect(CRect(0,0,sz.cx,sz.cy), &CBrush(RGB(255,255,255)));
              
bRet = pIDrawer->Draw(&memTmpDC);
            
}
          
}
          ::
DeleteObject(hBMP);
        
}
        ::
CloseHandle(hMap);
      
}
    
}
    ::
CloseHandle(hFile);
 
}
 
if(!bRet)
    ::
DeleteFile(lpszFileName);
 
return bRet;
}

Win32/MFC , ,

  1. No comments yet.
  1. No trackbacks yet.