16 Dec
Posted by hamo as Win32/MFC 959 views
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.
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;
}
Permalink: Code Library - Simple code to create an EMF or Bitmap file from existed draw code
Subcribe the update with Google Reader.
RSS feed for comments on this post · TrackBack URI
Leave a reply