这是一个图片加载与绘制的类,使用GDI将图片文件绘制到DC上,可以用于图片显示,程序换肤等应用场合。
其中部分代码来源于互联网,代码作者不详,我只进行了改进和增补,如果来源作者看到,还望谅解。
一、头文件(CEnBitmap.h)
/**///////////////////////////////////////////////////////////////////////////
///
/// @file EnBitmap.h
///
/// @brief Inherite from CBitmap, expanding some draw features
///
/// @author XuYu
/// @version 1.0
/// @date 2007-07-26
///
//////////////////////////////////////////////////////////////////////////
#if !defined(AFX_ENBITMAP_H__76F269F6_895A_48EC_BA09_7D3BEF0438E7__INCLUDED_)
#define AFX_ENBITMAP_H__76F269F6_895A_48EC_BA09_7D3BEF0438E7__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CEnBitmap : public CBitmap
...{
public:
CEnBitmap();
virtual ~CEnBitmap();
BOOL LoadImage(UINT uIDRes, LPCTSTR szResourceType, HMODULE hInst = NULL, COLORREF crBack = 0);
BOOL LoadImage(LPCTSTR lpctImagePath, COLORREF crBack=0);
BOOL LoadImage(HBITMAP hBitmap);
BOOL LoadImage2(UINT uIDRes, LPCTSTR lpctResType, HMODULE hInst=NULL, COLORREF crBack=0);
int GetWidth()
...{
BITMAP bm;
memset( &bm, 0, sizeof(bm) );
GetBitmap(&bm);
return bm.bmWidth;
}
int GetHeight()
...{
BITMAP bm;
memset( &bm, 0, sizeof(bm) );
GetBitmap(&bm);
return bm.bmHeight;
}
CRect GetRect()
...{
return CRect(0, 0, GetWidth(), GetHeight());
}
BOOL ExtendDraw(CDC *pDC,CRect rc, int nX, int nY);
BOOL ExtendDrawImage(CEnBitmap &bmp, CRect rc, int nX, int nY);
BOOL StretchDraw(CDC *pDC, LPRECT r, LPRECT sr);
BOOL StretchDraw(CDC *pDC, LPRECT r);
BOOL Draw(CDC *pDC, LPRECT r);
private:
static int GetImageType(LPCTSTR lpctImagePath);
static HBITMAP ExtractBitmap(IPicture* pPicture, COLORREF crBack = 0);
static HBITMAP LoadImageFile(LPCTSTR lpctImagePath, COLORREF crBack = 0);
static HBITMAP LoadImageResource(UINT uIDRes, LPCTSTR szResourceType, HMODULE hInst = NULL, COLORREF crBack = 0);
static BOOL GetResource(LPCTSTR lpctName, LPCTSTR lpctType, HMODULE hInst, void* pRes, int& nBufSize);
static IPicture* LoadFromBuffer(BYTE* pBuff, int nSize);
BOOL AttachEx(IPicture* pPicture, COLORREF crBack);
};
#endif // !defined(AFX_ENBITMAP_H__76F269F6_895A_48EC_BA09_7D3BEF0438E7__INCLUDED_)
二、源文件(CEnBitmap.cpp)
#include "stdafx.h"
#include "EnBitmap.h"
/**//// Definition of picture type
enum
...{
FT_BMP,
FT_JPG,
FT_UNKNOWN
};
CEnBitmap::CEnBitmap()
...{
}
CEnBitmap::~CEnBitmap()
...{
}
/**///////////////////////////////////////////////////////////////////////////
///
/// @brief Get picture type, only support JPG and BMP
///
/// @param [in] lpctImagePath The picture full path
///
//////////////////////////////////////////////////////////////////////////
int CEnBitmap::GetImageType(LPCTSTR lpctImagePath)
...{
size_t nLen = _tcslen(lpctImagePath);
TCHAR* lptImagePath = new TCHAR[nLen+1];
memset(lptImagePath,0,nLen+1);
_tcscpy(lptImagePath, lpctImagePath);
CharUpper(lptImagePath);
TCHAR lptExtension[5] = ...{0};
size_t i=nLen-4;
size_t j=0;
for(; i<nLen; i++,j++)
lptExtension[j] = lptImagePath[i];
delete[] lptImagePath;
if(_tcscmp(lptExtension,_T(".BMP")) == 0)
return FT_BMP;
if(_tcscmp(lptExtension,_T(".JPG")) == 0)
return FT_JPG;
return FT_UNKNOWN;
}
/**///////////////////////////////////////////////////////////////////////////
///
/// @brief Extract a picture use IPicture interface
///
/// @param [in] pPicture IPicture interface pointer
/// @param [in] crBack Mask color to make transparent
///
//////////////////////////////////////////////////////////////////////////
HBITMAP CEnBitmap::ExtractBitmap(IPicture* pPicture, COLORREF crBack /**//* = 0 */)
...{
ATLASSERT(pPicture);
if (!pPicture)
return NULL;
CBitmap bmMem;
CDC dcMem;
HWND hwndDesktopWnd = ::GetDesktopWindow();
HDC hDesktopDC = ::GetDC(hwndDesktopWnd);
CDC* pDC = new CDC(hDesktopDC);
if (dcMem.CreateCompatibleDC(pDC->m_hDC))
...{
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->m_hDC, nWidth, nHeight))
...{
HBITMAP hOldBM = dcMem.SelectBitmap(bmMem.m_hBitmap);
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.SelectBitmap(hOldBM);
}
}
::ReleaseDC(hwndDesktopWnd, pDC->m_hDC);
if(dcMem.m_hDC) ::DeleteDC(dcMem.Detach());
::DeleteObject(hDesktopDC);
if(pDC->m_hDC) ::DeleteDC(pDC->Detach());
return (HBITMAP)bmMem.Detach();
}
/**///////////////////////////////////////////////////////////////////////////
///
/// @brief Load a picture from full path
///
/// @param [in] lpctImagePath The full path of picture
/// @param [in] crBack Mask color to make transparent
///
//////////////////////////////////////////////////////////////////////////
HBITMAP CEnBitmap::LoadImageFile(LPCTSTR lpctImagePath, COLORREF crBack /**//* = 0 */)
...{
int nImgType = GetImageType(lpctImagePath);
USES_CONVERSION;
switch(nImgType)
...{
case FT_BMP:
return (HBITMAP)::LoadImage(NULL, lpctImagePath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
case FT_UNKNOWN:
return NULL;
default:
...{
IPicture* pPic = NULL;
HBITMAP hbm = NULL;
HRESULT hr = OleLoadPicturePath(T2OLE((LPTSTR)lpctImagePath), NULL, 0, crBack, IID_IPicture, (LPVOID *)&pPic);
if(pPic)
...{
hbm = ExtractBitmap(pPic, crBack);
pPic->Release();
}
return hbm;
}
}
return NULL;
}
/**///////////////////////////////////////////////////////////////////////////
///
/// @brief Load a picture from resource ID
///
/// @param [in] uIDRes Resource ID
/// @param [in] szResourceType Resource type
/// @param [in] hInst Instance including resources
/// @param [in] crBack Mask color to make transparent
///
/// @note This method need to valid
///
//////////////////////////////////////////////////////////////////////////
HBITMAP CEnBitmap::LoadImageResource(UINT uIDRes, LPCTSTR szResourceType, HMODULE hInst /**//* = NULL */, COLORREF crBack /**//* = 0 */)
...{
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;
}
/**///////////////////////////////////////////////////////////////////////////
///
/// @brief Load a picture from full path of picture
///
/// @param [in] lpctImagePath Full path of picture
/// @param [in] crBack Mask color to make transparent
///
/// @note This is the entry method
///
//////////////////////////////////////////////////////////////////////////
BOOL CEnBitmap::LoadImage(LPCTSTR lpctImagePath, COLORREF crBack/**//* =0 */)
...{
if(m_hBitmap != NULL)
...{
DeleteObject();
Detach();
}
Attach(LoadImageFile(lpctImagePath, crBack));
return (m_hBitmap == NULL) ? FALSE : TRUE;
}
/**///////////////////////////////////////////////////////////////////////////
///
/// @brief Load a picture from resource ID and type
///
/// @param [in] uIDRes Resource ID
/// @param [in] szResourceType Resource type
/// @param [in] hInst Instance including resources
/// @param [in] crBack Mask color to make transparent
///
/// @note This is the entry method
///
//////////////////////////////////////////////////////////////////////////
BOOL CEnBitmap::LoadImage(UINT uIDRes, LPCTSTR szResourceType, HMODULE hInst /**//* = NULL */, COLORREF crBack /**//* = 0 */)
...{
ATLASSERT(m_hBitmap == NULL);
if (m_hBitmap != NULL)
return TRUE;
Attach(LoadImageResource(uIDRes, szResourceType, hInst, crBack));
return (m_hBitmap == NULL) ? FALSE : TRUE;
}
/**///////////////////////////////////////////////////////////////////////////
///
/// @brief Load a bitmap from handle
///
/// @param [in] hBitmap Handle of a bitmap
///
/// @note This method need to valid
///
//////////////////////////////////////////////////////////////////////////
BOOL CEnBitmap::LoadImage(HBITMAP hBitmap)
...{
if(m_hBitmap != NULL)
...{
DeleteObject();
Detach();
}
Attach(hBitmap);
return (m_hBitmap == NULL) ? FALSE : TRUE;
}
/**///////////////////////////////////////////////////////////////////////////
///
/// @brief Load a picture from resource ID
///
/// @param [in] uIDRes Resource ID
/// @param [in] szResourceType Resource type
/// @param [in] hInst Instance including resources
/// @param [in] crBack Mask color to make transparent
///
/// @note This method is just for TESTING, DONT'T CALL this method before validation
///
//////////////////////////////////////////////////////////////////////////
BOOL CEnBitmap::LoadImage2(UINT uIDRes, LPCTSTR lpctResType, HMODULE hInst/**//* =NULL */, COLORREF crBack/**//* =0 */)
...{
ATLASSERT(m_hBitmap == NULL); // only attach once, detach on destroy
// if (m_hBitmap != NULL)
// return FALSE;
// if( (m_hBitmap = ::LoadBitmap(_Module.m_hInst,MAKEINTRESOURCE(uIDRes)) ) != NULL)
// return TRUE;
//
// return FALSE;
BYTE* pBuff = NULL;
int nSize = 0;
BOOL bResult = FALSE;
// first call is to get buffer size
if (GetResource(MAKEINTRESOURCE(uIDRes), lpctResType, hInst, 0, nSize))
...{
if (nSize > 0)
...{
pBuff = new BYTE[nSize];
// this loads it
if (GetResource(MAKEINTRESOURCE(uIDRes), lpctResType, hInst, pBuff, nSize))
...{
IPicture* pPicture = LoadFromBuffer(pBuff, nSize);
if (pPicture)
...{
bResult = AttachEx(pPicture, crBack);
pPicture->Release();
}
}
delete [] pBuff;
}
}
return bResult;
}
/**///////////////////////////////////////////////////////////////////////////
///
/// @brief Make a IPicture interface pointer from buffer stream
///
/// @param [in] pBuff Picture buffer stream
/// @param [in] nSize Size of pBuff
///
/// @note This method need to valid
///
//////////////////////////////////////////////////////////////////////////
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();
}
::GlobalFree(hGlobal);
return pPicture; // caller releases
}
/**///////////////////////////////////////////////////////////////////////////
///
/// @brief Get resource from a module
///
/// @param [in] lpName Resource name
/// @param [in] lpType Resource type
/// @param [in] hInst Handle of module
/// @param [out] pResource Resource pointer
/// @param [in] nBufSize Size of resource
///
/// @note This method need to valid
///
//////////////////////////////////////////////////////////////////////////
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;
}
/**///////////////////////////////////////////////////////////////////////////
///
/// @brief Attach a picture from IPicture interface pointer
///
/// @param [in] pPicture IPicture interface pointer
/// @param [in] crBack Mask color for making transparent
///
/// @note This method is called by LoadImage2, a TESTING function,
/// so DON'T USE THIS METHOD before validation
///
//////////////////////////////////////////////////////////////////////////
BOOL CEnBitmap::AttachEx(IPicture* pPicture, COLORREF crBack)
...{
ATLASSERT(m_hBitmap == NULL); // only attach once, detach on destroy
if (m_hBitmap != NULL)
return FALSE;
ATLASSERT(pPicture);
if (!pPicture)
return FALSE;
BOOL bResult = FALSE;
CDC dcMem;
CWindowDC dc(GetDesktopWindow());
CDC* pDC = &dc;
if (dcMem.CreateCompatibleDC(pDC->m_hDC))
...{
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);
CBitmap bmMem;
if (bmMem.CreateCompatibleBitmap(pDC->m_hDC, nWidth, nHeight))
...{
HBITMAP hOldBM = dcMem.SelectBitmap(bmMem.m_hBitmap);
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.SelectBitmap(hOldBM);
if (hr == S_OK)
/**//*bResult = */CBitmap::Attach(bmMem.Detach());
}
if(bmMem.m_hBitmap) bmMem.DeleteObject();
}
ReleaseDC(GetDesktopWindow(),pDC->m_hDC);
if(dcMem.m_hDC) ::DeleteDC(dcMem.Detach());
return bResult;
}
BOOL CEnBitmap::ExtendDraw(CDC *pDC, CRect rc, int nX, int nY)
...{
CEnBitmap bmp;
if (ExtendDrawImage(bmp,rc,nX,nY))
...{
bmp.Draw(pDC, &rc);
return TRUE;
}
return FALSE;
}
BOOL CEnBitmap::ExtendDrawImage(CEnBitmap &bmp, CRect rc, int nX, int nY)
...{
HBITMAP hOldBmp;
CDC memDC;
CClientDC cdc(0);
memDC.CreateCompatibleDC(cdc.m_hDC);
bmp.CreateCompatibleBitmap(cdc.m_hDC, rc.Width() , rc.Height() );
hOldBmp = memDC.SelectBitmap( bmp.m_hBitmap );
if (nX==0 && nY==0)
...{
StretchDraw(&memDC, &rc, GetRect());
return TRUE;
}
CDC dc;
dc.CreateCompatibleDC(memDC.m_hDC);
HBITMAP hBmp = dc.SelectBitmap( m_hBitmap );
//dc.SetStretchBltMode(COLORONCOLOR);
if (nX!=0 && nY==0)
...{
//左上角
memDC.BitBlt( 0, 0, nX, rc.Height(), dc.m_hDC, 0, 0, SRCCOPY );
memDC.StretchBlt(nX, 0, rc.Width()-GetWidth(), rc.Height(), dc.m_hDC,nX, 0, 1, GetHeight(), SRCCOPY );
//右上角
memDC.BitBlt(rc.right-(GetWidth()-nX), 0, GetWidth()-nX, rc.Height(), dc.m_hDC,nX, 0, SRCCOPY );
}
else if (nX==0 && nY!=0)
...{
//上角
memDC.BitBlt( 0, 0, rc.Width(), nY, dc.m_hDC, 0, 0, SRCCOPY );
memDC.StretchBlt(0, nY, GetWidth(), rc.Height()-GetHeight(), dc.m_hDC,0, nY, GetWidth(), 1, SRCCOPY );
//右上角
memDC.BitBlt(0, rc.bottom-(GetHeight()-nY), GetWidth(), GetHeight()-nY, dc.m_hDC,0, nY, SRCCOPY );
}
else
...{
//左上角
memDC.StretchBlt( 0, 0, nX, nY, dc.m_hDC, 0, 0, nX, nY, SRCCOPY );
//上中
memDC.StretchBlt(nX, 0, rc.Width()-GetWidth(),nY, dc.m_hDC, nX, 0, 1, nY , SRCCOPY );
//右上角
memDC.StretchBlt(rc.Width()-(GetWidth()-nX), 0, GetWidth()-nX, nY , dc.m_hDC,nX, 0, GetWidth()-nX, nY, SRCCOPY );
//左中
memDC.StretchBlt(0, nY, nX,rc.Height()-GetHeight(), dc.m_hDC, 0, nY, nX, 1, SRCCOPY );
//正中
memDC.StretchBlt(nX, nY, rc.Width()-GetWidth(),rc.Height()-GetHeight(), dc.m_hDC, nX, nY, 1, 1, SRCCOPY );
//右中
memDC.StretchBlt(rc.Width()-(GetWidth()-nX), nY, GetWidth()-nX,rc.Height()-GetHeight(), dc.m_hDC, nX, nY, GetWidth()-nX, 1, SRCCOPY );
//左下角
memDC.StretchBlt( 0, rc.Height()-(GetHeight()-nY), nX, GetHeight()-nY, dc.m_hDC, 0, nY, nX,GetHeight()-nY , SRCCOPY );
//下中
memDC.StretchBlt(nX, rc.Height()-(GetHeight()-nY), rc.Width()-GetWidth(),GetHeight()-nY, dc.m_hDC, nX, nY, 1, GetHeight()-nY, SRCCOPY );
//右下角
memDC.StretchBlt( rc.Width()-(GetWidth()-nX), rc.Height()-(GetHeight()-nY), GetWidth()-nX, GetHeight()-nY, dc.m_hDC, nX, nY, GetWidth()-nX, GetHeight()-nY, SRCCOPY );
}
dc.SelectBitmap( hBmp );
memDC.SelectBitmap(hOldBmp);
memDC.Detach();
//cdc.Detach();
dc.Detach();
return TRUE;
}
BOOL CEnBitmap::StretchDraw(CDC *pDC, LPRECT r, LPRECT sr )
...{
if ( !r )
return FALSE;
CDC dc;
dc.CreateCompatibleDC( pDC->m_hDC );
HBITMAP hOldBitmap = dc.SelectBitmap( m_hBitmap );
pDC->SetStretchBltMode(COLORONCOLOR);
if ( !sr )
pDC->StretchBlt( r->left, r->top, r->right, r->bottom, dc.m_hDC, 0, 0, GetWidth(), GetHeight(), SRCCOPY );
else
pDC->StretchBlt( r->left, r->top,
r->right - r->left,
r->bottom - r->top,
dc.m_hDC,
sr->left,
sr->top,
sr->right - sr->left,
sr->bottom - sr->top,
SRCCOPY );
dc.SelectBitmap( hOldBitmap );
if(dc.m_hDC) ::DeleteDC(dc.Detach());
::DeleteObject(hOldBitmap);
hOldBitmap = NULL;
return TRUE;
}
BOOL CEnBitmap::StretchDraw(CDC *pDC, LPRECT r)
...{
CDC dc;
dc.CreateCompatibleDC( pDC->m_hDC );
HBITMAP bmp = dc.SelectBitmap( m_hBitmap );
pDC->StretchBlt( r->left, r->top, r->right, r->bottom, dc.m_hDC, 0, 0, GetWidth(), GetHeight(), SRCCOPY );
dc.SelectBitmap( bmp );
if(dc.m_hDC) ::DeleteDC(dc.Detach());
::DeleteObject(bmp);
bmp = NULL;
return TRUE;
}
BOOL CEnBitmap::Draw(CDC *pDC, LPRECT r)
...{
CDC dc;
dc.CreateCompatibleDC( pDC->m_hDC );
HBITMAP bmp = dc.SelectBitmap( m_hBitmap );
pDC->BitBlt( r->left, r->top, r->right - r->left, r->bottom - r->top, dc.m_hDC, 0, 0, SRCCOPY );
dc.SelectBitmap( bmp );
::DeleteDC(dc.Detach());
return TRUE;
}