// EnBitmap.cpp: implementation of the CEnBitmap class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "EnBitmap.h"
#include <AFXPRIV.H>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
const int HIMETRIC_INCH = 2540;
enum
{
FT_BMP,
FT_ICO,
FT_JPG,
FT_GIF,
FT_UNKNOWN
};
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CEnBitmap::CEnBitmap()
{
}
CEnBitmap::~CEnBitmap()
{
}
BOOL CEnBitmap::LoadImage(UINT uIDRes, LPCTSTR szResourceType, HMODULE hInst, COLORREF crBack)
{
ASSERT(m_hObject == NULL); // only attach once, detach on destroy
if (m_hObject != NULL)
return FALSE;
return Attach(LoadImageResource(uIDRes, szResourceType, hInst, crBack));
}
BOOL CEnBitmap::LoadImage(LPCTSTR szImagePath, COLORREF crBack)
{
ASSERT(m_hObject == NULL); // only attach once, detach on destroy
if (m_hObject != NULL)
return FALSE;
return Attach(LoadImageFile(szImagePath, crBack));
}
HBITMAP CEnBitmap::LoadImageFile(LPCTSTR szImagePath, COLORREF crBack)
{
int nType = GetFileType(szImagePath);
switch (nType)
{
// i suspect it is more efficient to load
// bmps this way since it avoids creating device contexts etc that the
// IPicture methods requires. that method however is still valuable
// since it handles other image types and transparency
case FT_BMP:
return (HBITMAP)::LoadImage(NULL, szImagePath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
case FT_UNKNOWN:
return NULL;
default: // all the rest
{
USES_CONVERSION;
IPicture* pPicture = NULL;
HBITMAP hbm = NULL;
HRESULT hr = OleLoadPicturePath(T2OLE(szImagePath), NULL, 0, crBack, IID_IPicture, (LPVOID *)&pPicture);
if (pPicture)
{
hbm = ExtractBitmap(pPicture, crBack);
pPicture->Release();
}
return hbm;
}
}
return NULL; // can't get here
}
HBITMAP CEnBitmap::LoadImageResource(UINT uIDRes, LPCTSTR szResourceType, HMODULE hInst, COLORREF crBack)
{
BYTE* pBuff = NULL;
int nSize = 0;
HBITMAP hbm = NULL;
// first call is to get buffer size
if (GetResource(MAKEINTRESOURCE(uIDRes), szResourceType, hInst, 0, nSize))
{
if (nSize > 0)
{
pBuff = new BYTE[nSize];
// this loads it
if (GetResource(MAKEINTRESOURCE(uIDRes), szResourceType, hInst, pBuff, nSize))
{
IPicture* pPicture = LoadFromBuffer(pBuff, nSize);
if (pPicture)
{
hbm = ExtractBitmap(pPicture, crBack);
pPicture->Release();
}
}
delete [] pBuff;
}
}
return hbm;
}
IPicture* CEnBitmap::LoadFromBuffer(BYTE* pBuff, int nSize)
{
bool bResult = false;
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, nSize);
void* pData = GlobalLock(hGlobal);
memcpy(pData, pBuff, nSize);
GlobalUnlock(hGlobal);
IStream* pStream = NULL;
IPicture* pPicture = NULL;
if (CreateStreamOnHGlobal(hGlobal, TRUE, &pStream) == S_OK)
{
HRESULT hr = OleLoadPicture(pStream, nSize, FALSE, IID_IPicture, (LPVOID *)&pPicture);
pStream->Release();
}
return pPicture; // caller releases
}
BOOL CEnBitmap::GetResource(LPCTSTR lpName, LPCTSTR lpType, HMODULE hInst, void* pResource, int& nBufSize)
{
HRSRC hResInfo;
HANDLE hRes;
LPSTR lpRes = NULL;
int nLen = 0;
bool bResult = FALSE;
// Find the resource
hResInfo = FindResource(hInst, lpName, lpType);
if (hResInfo == NULL)
return false;
// Load the resource
hRes = LoadResource(hInst, hResInfo);
if (hRes == NULL)
return false;
// Lock the resource
lpRes = (char*)LockResource(hRes);
if (lpRes != NULL)
{
if (pResource == NULL)
{
nBufSize = SizeofResource(hInst, hResInfo);
bResult = true;
}
else
{
if (nBufSize >= (int)SizeofResource(hInst, hResInfo))
{
memcpy(pResource, lpRes, nBufSize);
bResult = true;
}
}
UnlockResource(hRes);
}
// Free the resource
FreeResource(hRes);
return bResult;
}
HBITMAP CEnBitmap::ExtractBitmap(IPicture* pPicture, COLORREF crBack)
{
ASSERT(pPicture);
if (!pPicture)
return NULL;
CBitmap bmMem;
CDC dcMem;
CDC* pDC = CWnd::GetDesktopWindow()->GetDC();
if (dcMem.CreateCompatibleDC(pDC))
{
long hmWidth;
long hmHeight;
pPicture->get_Width(&hmWidth);
pPicture->get_Height(&hmHeight);
int nWidth = MulDiv(hmWidth, pDC->GetDeviceCaps(LOGPIXELSX), HIMETRIC_INCH);
int nHeight = MulDiv(hmHeight, pDC->GetDeviceCaps(LOGPIXELSY), HIMETRIC_INCH);
if (bmMem.CreateCompatibleBitmap(pDC, nWidth, nHeight))
{
CBitmap* pOldBM = dcMem.SelectObject(&bmMem);
if (crBack != -1)
dcMem.FillSolidRect(0, 0, nWidth, nHeight, crBack);
HRESULT hr = pPicture->Render(dcMem, 0, 0, nWidth, nHeight, 0, hmHeight, hmWidth, -hmHeight, NULL);
dcMem.SelectObject(pOldBM);
}
}
CWnd::GetDesktopWindow()->ReleaseDC(pDC);
return (HBITMAP)bmMem.Detach();
}
int CEnBitmap::GetFileType(LPCTSTR szImagePath)
{
CString sPath(szImagePath);
sPath.MakeUpper();
if (sPath.Find(".BMP") > 0)
return FT_BMP;
else if (sPath.Find(".ICO") > 0)
return FT_ICO;
else if (sPath.Find(".JPG") > 0 || sPath.Find(".JPEG") > 0)
return FT_JPG;
else if (sPath.Find(".GIF") > 0)
return FT_GIF;
// else
return FT_UNKNOWN;
}