在《一个图片加载与绘制类(使用GDI输出图片)》中我公布了基本的图片加载和绘制类,我们可以再根据这个类派生一些我们需要的新的绘制类,来针对某些特殊情况的绘制和使用,下面我再公布一个这样的类,作为样例。其中部分代码来源于互联网。
一、头文件(CImageLoader.h)
#include "EnBitmap.h"
class CImageLoader : public CEnBitmap
{
public:
BOOL DrawImage(CEnBitmap& bmp, int nX, int nY, int nCol, int nRow);
CImageLoader();
virtual ~CImageLoader();
BOOL Draw( CDC *pDC, LPRECT r);
//draw sub bmp to special point
BOOL Draw( CDC *pDC, int x, int y, LPRECT sr );
BOOL Draw( CDC *pDC, int x, int y, LPRECT sr, COLORREF colTrans, BOOL bTrans );
BOOL DrawByHeight(CDC* pDC, int x, int y, int sx, int sy, LPRECT sr, int nHeight);
int Width(){ return GetWidth(); }
int Height(){ return GetHeight(); }
void Attach(HBITMAP hbmp) { CBitmap::Attach(hbmp); }
BOOL LoadBitmap(UINT nResName, HMODULE hInst=NULL, COLORREF crBack=0)
{
if(m_hBitmap) DeleteObject();
return LoadImage(nResName,RT_BITMAP,hInst,crBack);
}
BOOL LoadBitmap(LPCTSTR lpctImagePath, COLORREF crBack=0)
{
if(m_hBitmap) DeleteObject();
return LoadImage(lpctImagePath,crBack);
}
BOOL DrawTransparent(CDC * pDC, int x, int y, COLORREF crColour);
HRGN CreateRgnFromFile( COLORREF color );
BOOL DrawImageByIndex(CDC* pDC, CRect rect, int nIndex, COLORREF clrTrans, BOOL bTrans);
};
class CImageLoader : public CEnBitmap
{
public:
BOOL DrawImage(CEnBitmap& bmp, int nX, int nY, int nCol, int nRow);
CImageLoader();
virtual ~CImageLoader();
BOOL Draw( CDC *pDC, LPRECT r);
//draw sub bmp to special point
BOOL Draw( CDC *pDC, int x, int y, LPRECT sr );
BOOL Draw( CDC *pDC, int x, int y, LPRECT sr, COLORREF colTrans, BOOL bTrans );
BOOL DrawByHeight(CDC* pDC, int x, int y, int sx, int sy, LPRECT sr, int nHeight);
int Width(){ return GetWidth(); }
int Height(){ return GetHeight(); }
void Attach(HBITMAP hbmp) { CBitmap::Attach(hbmp); }
BOOL LoadBitmap(UINT nResName, HMODULE hInst=NULL, COLORREF crBack=0)
{
if(m_hBitmap) DeleteObject();
return LoadImage(nResName,RT_BITMAP,hInst,crBack);
}
BOOL LoadBitmap(LPCTSTR lpctImagePath, COLORREF crBack=0)
{
if(m_hBitmap) DeleteObject();
return LoadImage(lpctImagePath,crBack);
}
BOOL DrawTransparent(CDC * pDC, int x, int y, COLORREF crColour);
HRGN CreateRgnFromFile( COLORREF color );
BOOL DrawImageByIndex(CDC* pDC, CRect rect, int nIndex, COLORREF clrTrans, BOOL bTrans);
};
二、源文件(CImageLoader.cpp)
#include "stdafx.h"
#include "GnetImageLoader.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CImageLoader::CImageLoader()
{
}
CImageLoader::~CImageLoader()
{
}
BOOL CImageLoader::Draw( CDC *pDC, int x, int y, LPRECT sr, COLORREF colTrans, BOOL bTrans )
{
if ( !bTrans )
Draw( pDC ,x, y, sr );
else
{
MyTransparentBlt( pDC->m_hDC, x, y, sr->right - sr->left, sr->bottom - sr->top,
m_hBitmap, sr->left, sr->top, colTrans, NULL );
}
return TRUE;
}
//draw sub bmp to special point
BOOL CImageLoader::Draw( CDC *pDC, int x, int y, LPRECT sr )
{
CDC dc;
dc.CreateCompatibleDC( pDC->m_hDC );
HBITMAP bmp = dc.SelectBitmap( m_hBitmap );
if ( sr != NULL)
pDC->BitBlt( x, y, sr->right - sr->left, sr->bottom - sr->top, dc.m_hDC,
sr->left, sr->top, SRCCOPY );
else
pDC->BitBlt( x, y, Width(), Height(), dc.m_hDC,
0, 0, SRCCOPY );
dc.SelectBitmap( bmp );
if(dc.m_hDC) ::DeleteDC(dc.Detach());
return TRUE;
}
BOOL CImageLoader::DrawByHeight(CDC* pDC, int x, int y, int sx, int sy, LPRECT sr, int nHeight)
{
CDC dc;
dc.CreateCompatibleDC(pDC->m_hDC);
HBITMAP hBitmap = dc.SelectBitmap(m_hBitmap);
if(sr == NULL)
pDC->BitBlt(x, y, Width(), Height(), dc.m_hDC, 0, 0, SRCCOPY);
else
{
int nSrcWidth = sr->right - sr->left;
int nSrcHeight = sr->bottom - sr->top;
if(nSrcHeight == nHeight)
pDC->BitBlt(x, y, nSrcWidth, nSrcHeight, dc.m_hDC, sr->left, sr->top, SRCCOPY);
else
{
//高度不同,需要拉伸绘制(根据指定的高度值:nHeight)
pDC->StretchBlt(x, y, sr->right-sr->left, nHeight, dc.m_hDC, sx, sy, nSrcWidth, nSrcHeight, SRCCOPY);
}
}
dc.SelectBitmap(hBitmap);
::DeleteDC(dc.Detach());
return TRUE;
}
BOOL CImageLoader::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 );
if(dc.m_hDC) ::DeleteDC(dc.Detach());
return TRUE;
}
///HOWTO: Drawing Transparent Bitmaps
//see: Microsoft Knowledge Base Article - Q79212
BOOL CImageLoader::DrawTransparent(CDC * pDC, int x, int y, COLORREF crColour)
{
MyTransparentBlt( pDC->m_hDC, x, y, GetWidth(), GetHeight(), m_hBitmap, 0, 0, crColour, NULL );
return TRUE;
}
HRGN CImageLoader::CreateRgnFromFile( COLORREF color )
{
HBITMAP hBmp = m_hBitmap;
// get image properties
BITMAP bmp = { 0 };
::GetObject( hBmp, sizeof(BITMAP), &bmp );
// allocate memory for extended image information
LPBITMAPINFO bi = (LPBITMAPINFO) new BYTE[ sizeof(BITMAPINFO) + 8 ];
memset( bi, 0, sizeof(BITMAPINFO) + 8 );
bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
// set window size
int m_dwWidth = bmp.bmWidth; // bitmap width
int m_dwHeight = bmp.bmHeight; // bitmap height
// create temporary dc
HDC dc = CreateIC( "DISPLAY",NULL,NULL,NULL );
// get extended information about image (length, compression, length of color table if exist, ...)
DWORD res = ::GetDIBits( dc, hBmp, 0, bmp.bmHeight, 0, bi, DIB_RGB_COLORS );
// allocate memory for image data (colors)
LPBYTE pBits = new BYTE[ bi->bmiHeader.biSizeImage + 4 ];
// allocate memory for color table
if ( bi->bmiHeader.biBitCount == 8 )
{
// actually color table should be appended to this header(BITMAPINFO),
// so we have to reallocate and copy it
LPBITMAPINFO old_bi = bi;
// 255 - because there is one in BITMAPINFOHEADER
bi = (LPBITMAPINFO)new char[ sizeof(BITMAPINFO) + 255 * sizeof(RGBQUAD) ];
memcpy( bi, old_bi, sizeof(BITMAPINFO) );
// release old header
delete old_bi;
}
// get bitmap info header
BITMAPINFOHEADER& bih = bi->bmiHeader;
// get color table (for 256 color mode contains 256 entries of RGBQUAD(=DWORD))
LPDWORD clr_tbl = (LPDWORD)&bi->bmiColors;
// fill bits buffer
res = ::GetDIBits( dc, hBmp, 0, bih.biHeight, pBits, bi, DIB_RGB_COLORS );
DeleteDC( dc );
BITMAP bm;
::GetObject( hBmp, sizeof(BITMAP), &bm );
// shift bits and byte per pixel (for comparing colors)
LPBYTE pClr = (LPBYTE)&color;
// swap red and blue components
BYTE tmp = pClr[0]; pClr[0] = pClr[2]; pClr[2] = tmp;
// convert color if curent DC is 16-bit (5:6:5) or 15-bit (5:5:5)
if ( bih.biBitCount == 16 )
{
// for 16 bit
color = ((DWORD)(pClr[0] & 0xf8) >> 3) |
((DWORD)(pClr[1] & 0xfc) << 3) |
((DWORD)(pClr[2] & 0xf8) << 8);
// for 15 bit
// color = ((DWORD)(pClr[0] & 0xf8) >> 3) |
// ((DWORD)(pClr[1] & 0xf8) << 2) |
// ((DWORD)(pClr[2] & 0xf8) << 7);
}
const DWORD RGNDATAHEADER_SIZE = sizeof(RGNDATAHEADER);
const DWORD ADD_RECTS_COUNT = 40; // number of rects to be appended
// to region data buffer
// BitPerPixel
BYTE Bpp = bih.biBitCount >> 3; // bytes per pixel
// bytes per line in pBits is DWORD aligned and bmp.bmWidthBytes is WORD aligned
// so, both of them not
DWORD m_dwAlignedWidthBytes = (bmp.bmWidthBytes & ~0x3) + (!!(bmp.bmWidthBytes & 0x3) << 2);
// DIB image is flipped that's why we scan it from the last line
LPBYTE pColor = pBits + (bih.biHeight - 1) * m_dwAlignedWidthBytes;
DWORD dwLineBackLen = m_dwAlignedWidthBytes + bih.biWidth * Bpp; // offset of previous scan line
// (after processing of current)
DWORD dwRectsCount = bih.biHeight; // number of rects in allocated buffer
INT i, j; // current position in mask image
INT first = 0; // left position of current scan line
// where mask was found
bool wasfirst = false; // set when mask has been found in current scan line
bool ismask; // set when current color is mask color
// allocate memory for region data
// region data here is set of regions that are rectangles with height 1 pixel (scan line)
// that's why first allocation is <bm.biHeight> RECTs - number of scan lines in image
RGNDATAHEADER* pRgnData =
(RGNDATAHEADER*)new BYTE[ RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) ];
// get pointer to RECT table
LPRECT pRects = (LPRECT)((LPBYTE)pRgnData + RGNDATAHEADER_SIZE);
// zero region data header memory (header part only)
memset( pRgnData, 0, RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) );
// fill it by default
pRgnData->dwSize = RGNDATAHEADER_SIZE;
pRgnData->iType = RDH_RECTANGLES;
for ( i = 0; i < bih.biHeight; i++ )
{
for ( j = 0; j < bih.biWidth; j++ )
{
// get color
switch ( bih.biBitCount )
{
case 8:
ismask = (clr_tbl[ *pColor ] != color);
break;
case 16:
ismask = (*(LPWORD)pColor != (WORD)color);
break;
case 24:
ismask = ((*(LPDWORD)pColor & 0x00ffffff) != color);
break;
case 32:
ismask = (*(LPDWORD)pColor != color);
}
// shift pointer to next color
pColor += Bpp;
// place part of scan line as RECT region if transparent color found after mask color or
// mask color found at the end of mask image
if ( wasfirst )
{
if ( !ismask )
{
// save current RECT
pRects[ pRgnData->nCount++ ] = CRect( first, i, j, i + 1 );
// if buffer full reallocate it with more room
if ( pRgnData->nCount >= dwRectsCount )
{
dwRectsCount += ADD_RECTS_COUNT;
// allocate new buffer
LPBYTE pRgnDataNew = new BYTE[ RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) ];
// copy current region data to it
memcpy( pRgnDataNew, pRgnData, RGNDATAHEADER_SIZE + pRgnData->nCount * sizeof(RECT) );
// delte old region data buffer
delete pRgnData;
// set pointer to new regiondata buffer to current
pRgnData = (RGNDATAHEADER*)pRgnDataNew;
// correct pointer to RECT table
pRects = (LPRECT)((LPBYTE)pRgnData + RGNDATAHEADER_SIZE);
}
wasfirst = false;
}
}
else if ( ismask ) // set wasfirst when mask is found
{
first = j;
wasfirst = true;
}
}
if ( wasfirst && ismask )
{
// save current RECT
pRects[ pRgnData->nCount++ ] = CRect( first, i, j, i + 1 );
// if buffer full reallocate it with more room
if ( pRgnData->nCount >= dwRectsCount )
{
dwRectsCount += ADD_RECTS_COUNT;
// allocate new buffer
LPBYTE pRgnDataNew = new BYTE[ RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) ];
// copy current region data to it
memcpy( pRgnDataNew, pRgnData, RGNDATAHEADER_SIZE + pRgnData->nCount * sizeof(RECT) );
// delte old region data buffer
delete pRgnData;
// set pointer to new regiondata buffer to current
pRgnData = (RGNDATAHEADER*)pRgnDataNew;
// correct pointer to RECT table
pRects = (LPRECT)((LPBYTE)pRgnData + RGNDATAHEADER_SIZE);
}
wasfirst = false;
}
pColor -= dwLineBackLen;
}
// release image data
delete pBits;
delete bi;
// create region
HRGN hRgn = ExtCreateRegion( NULL, RGNDATAHEADER_SIZE + pRgnData->nCount * sizeof(RECT), (LPRGNDATA)pRgnData );
// release region data
delete pRgnData;
return hRgn;
}
BOOL CImageLoader::DrawImage(CEnBitmap &bmp, int nX, int nY, int nCol, int nRow)
{
nX -= 1;
nY -= 1;
int w = GetWidth()/nCol;
int h = GetHeight()/nRow;
HBITMAP hOldBmp;
CDC memDC;
CClientDC dc(0);
memDC.CreateCompatibleDC(dc.m_hDC);
bmp.CreateCompatibleBitmap(dc.m_hDC, w, h);
hOldBmp = memDC.SelectBitmap(bmp.m_hBitmap);
StretchDraw( &memDC, CRect( 0, 0, w, h ),
CRect(GetWidth()*nX/nCol, GetHeight()*nY/nRow, GetWidth()*nX/nCol+w ,GetHeight()*nY/nRow+h ) );
memDC.SelectBitmap(hOldBmp);
//dc.DeleteDC();
memDC.DeleteDC();
::DeleteObject(hOldBmp);
hOldBmp = NULL;
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
///
/// @param [in] pDC Device context
/// @param [in] x
/// @param [in] y
/// @param [in] rect
/// @param [in] state Button state
/// - 0 : Normal
/// - 1 : Pressed
/// - 2 : Hover
/// - 3 : Disabled
/// @param [in] clrTrans
/// @param [in] bTrans
///
//////////////////////////////////////////////////////////////////////////
BOOL CImageLoader::DrawImageByIndex(CDC* pDC, CRect rect, int nIndex, COLORREF clrTrans, BOOL bTrans)
{
if(m_hBitmap == NULL) return FALSE;
Draw(pDC, rect.left, rect.top, CRect(nIndex*rect.Width(), 0, (nIndex+1)*rect.Width(), GetHeight()), clrTrans, bTrans);
return TRUE;
}
#include "GnetImageLoader.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CImageLoader::CImageLoader()
{
}
CImageLoader::~CImageLoader()
{
}
BOOL CImageLoader::Draw( CDC *pDC, int x, int y, LPRECT sr, COLORREF colTrans, BOOL bTrans )
{
if ( !bTrans )
Draw( pDC ,x, y, sr );
else
{
MyTransparentBlt( pDC->m_hDC, x, y, sr->right - sr->left, sr->bottom - sr->top,
m_hBitmap, sr->left, sr->top, colTrans, NULL );
}
return TRUE;
}
//draw sub bmp to special point
BOOL CImageLoader::Draw( CDC *pDC, int x, int y, LPRECT sr )
{
CDC dc;
dc.CreateCompatibleDC( pDC->m_hDC );
HBITMAP bmp = dc.SelectBitmap( m_hBitmap );
if ( sr != NULL)
pDC->BitBlt( x, y, sr->right - sr->left, sr->bottom - sr->top, dc.m_hDC,
sr->left, sr->top, SRCCOPY );
else
pDC->BitBlt( x, y, Width(), Height(), dc.m_hDC,
0, 0, SRCCOPY );
dc.SelectBitmap( bmp );
if(dc.m_hDC) ::DeleteDC(dc.Detach());
return TRUE;
}
BOOL CImageLoader::DrawByHeight(CDC* pDC, int x, int y, int sx, int sy, LPRECT sr, int nHeight)
{
CDC dc;
dc.CreateCompatibleDC(pDC->m_hDC);
HBITMAP hBitmap = dc.SelectBitmap(m_hBitmap);
if(sr == NULL)
pDC->BitBlt(x, y, Width(), Height(), dc.m_hDC, 0, 0, SRCCOPY);
else
{
int nSrcWidth = sr->right - sr->left;
int nSrcHeight = sr->bottom - sr->top;
if(nSrcHeight == nHeight)
pDC->BitBlt(x, y, nSrcWidth, nSrcHeight, dc.m_hDC, sr->left, sr->top, SRCCOPY);
else
{
//高度不同,需要拉伸绘制(根据指定的高度值:nHeight)
pDC->StretchBlt(x, y, sr->right-sr->left, nHeight, dc.m_hDC, sx, sy, nSrcWidth, nSrcHeight, SRCCOPY);
}
}
dc.SelectBitmap(hBitmap);
::DeleteDC(dc.Detach());
return TRUE;
}
BOOL CImageLoader::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 );
if(dc.m_hDC) ::DeleteDC(dc.Detach());
return TRUE;
}
///HOWTO: Drawing Transparent Bitmaps
//see: Microsoft Knowledge Base Article - Q79212
BOOL CImageLoader::DrawTransparent(CDC * pDC, int x, int y, COLORREF crColour)
{
MyTransparentBlt( pDC->m_hDC, x, y, GetWidth(), GetHeight(), m_hBitmap, 0, 0, crColour, NULL );
return TRUE;
}
HRGN CImageLoader::CreateRgnFromFile( COLORREF color )
{
HBITMAP hBmp = m_hBitmap;
// get image properties
BITMAP bmp = { 0 };
::GetObject( hBmp, sizeof(BITMAP), &bmp );
// allocate memory for extended image information
LPBITMAPINFO bi = (LPBITMAPINFO) new BYTE[ sizeof(BITMAPINFO) + 8 ];
memset( bi, 0, sizeof(BITMAPINFO) + 8 );
bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
// set window size
int m_dwWidth = bmp.bmWidth; // bitmap width
int m_dwHeight = bmp.bmHeight; // bitmap height
// create temporary dc
HDC dc = CreateIC( "DISPLAY",NULL,NULL,NULL );
// get extended information about image (length, compression, length of color table if exist, ...)
DWORD res = ::GetDIBits( dc, hBmp, 0, bmp.bmHeight, 0, bi, DIB_RGB_COLORS );
// allocate memory for image data (colors)
LPBYTE pBits = new BYTE[ bi->bmiHeader.biSizeImage + 4 ];
// allocate memory for color table
if ( bi->bmiHeader.biBitCount == 8 )
{
// actually color table should be appended to this header(BITMAPINFO),
// so we have to reallocate and copy it
LPBITMAPINFO old_bi = bi;
// 255 - because there is one in BITMAPINFOHEADER
bi = (LPBITMAPINFO)new char[ sizeof(BITMAPINFO) + 255 * sizeof(RGBQUAD) ];
memcpy( bi, old_bi, sizeof(BITMAPINFO) );
// release old header
delete old_bi;
}
// get bitmap info header
BITMAPINFOHEADER& bih = bi->bmiHeader;
// get color table (for 256 color mode contains 256 entries of RGBQUAD(=DWORD))
LPDWORD clr_tbl = (LPDWORD)&bi->bmiColors;
// fill bits buffer
res = ::GetDIBits( dc, hBmp, 0, bih.biHeight, pBits, bi, DIB_RGB_COLORS );
DeleteDC( dc );
BITMAP bm;
::GetObject( hBmp, sizeof(BITMAP), &bm );
// shift bits and byte per pixel (for comparing colors)
LPBYTE pClr = (LPBYTE)&color;
// swap red and blue components
BYTE tmp = pClr[0]; pClr[0] = pClr[2]; pClr[2] = tmp;
// convert color if curent DC is 16-bit (5:6:5) or 15-bit (5:5:5)
if ( bih.biBitCount == 16 )
{
// for 16 bit
color = ((DWORD)(pClr[0] & 0xf8) >> 3) |
((DWORD)(pClr[1] & 0xfc) << 3) |
((DWORD)(pClr[2] & 0xf8) << 8);
// for 15 bit
// color = ((DWORD)(pClr[0] & 0xf8) >> 3) |
// ((DWORD)(pClr[1] & 0xf8) << 2) |
// ((DWORD)(pClr[2] & 0xf8) << 7);
}
const DWORD RGNDATAHEADER_SIZE = sizeof(RGNDATAHEADER);
const DWORD ADD_RECTS_COUNT = 40; // number of rects to be appended
// to region data buffer
// BitPerPixel
BYTE Bpp = bih.biBitCount >> 3; // bytes per pixel
// bytes per line in pBits is DWORD aligned and bmp.bmWidthBytes is WORD aligned
// so, both of them not
DWORD m_dwAlignedWidthBytes = (bmp.bmWidthBytes & ~0x3) + (!!(bmp.bmWidthBytes & 0x3) << 2);
// DIB image is flipped that's why we scan it from the last line
LPBYTE pColor = pBits + (bih.biHeight - 1) * m_dwAlignedWidthBytes;
DWORD dwLineBackLen = m_dwAlignedWidthBytes + bih.biWidth * Bpp; // offset of previous scan line
// (after processing of current)
DWORD dwRectsCount = bih.biHeight; // number of rects in allocated buffer
INT i, j; // current position in mask image
INT first = 0; // left position of current scan line
// where mask was found
bool wasfirst = false; // set when mask has been found in current scan line
bool ismask; // set when current color is mask color
// allocate memory for region data
// region data here is set of regions that are rectangles with height 1 pixel (scan line)
// that's why first allocation is <bm.biHeight> RECTs - number of scan lines in image
RGNDATAHEADER* pRgnData =
(RGNDATAHEADER*)new BYTE[ RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) ];
// get pointer to RECT table
LPRECT pRects = (LPRECT)((LPBYTE)pRgnData + RGNDATAHEADER_SIZE);
// zero region data header memory (header part only)
memset( pRgnData, 0, RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) );
// fill it by default
pRgnData->dwSize = RGNDATAHEADER_SIZE;
pRgnData->iType = RDH_RECTANGLES;
for ( i = 0; i < bih.biHeight; i++ )
{
for ( j = 0; j < bih.biWidth; j++ )
{
// get color
switch ( bih.biBitCount )
{
case 8:
ismask = (clr_tbl[ *pColor ] != color);
break;
case 16:
ismask = (*(LPWORD)pColor != (WORD)color);
break;
case 24:
ismask = ((*(LPDWORD)pColor & 0x00ffffff) != color);
break;
case 32:
ismask = (*(LPDWORD)pColor != color);
}
// shift pointer to next color
pColor += Bpp;
// place part of scan line as RECT region if transparent color found after mask color or
// mask color found at the end of mask image
if ( wasfirst )
{
if ( !ismask )
{
// save current RECT
pRects[ pRgnData->nCount++ ] = CRect( first, i, j, i + 1 );
// if buffer full reallocate it with more room
if ( pRgnData->nCount >= dwRectsCount )
{
dwRectsCount += ADD_RECTS_COUNT;
// allocate new buffer
LPBYTE pRgnDataNew = new BYTE[ RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) ];
// copy current region data to it
memcpy( pRgnDataNew, pRgnData, RGNDATAHEADER_SIZE + pRgnData->nCount * sizeof(RECT) );
// delte old region data buffer
delete pRgnData;
// set pointer to new regiondata buffer to current
pRgnData = (RGNDATAHEADER*)pRgnDataNew;
// correct pointer to RECT table
pRects = (LPRECT)((LPBYTE)pRgnData + RGNDATAHEADER_SIZE);
}
wasfirst = false;
}
}
else if ( ismask ) // set wasfirst when mask is found
{
first = j;
wasfirst = true;
}
}
if ( wasfirst && ismask )
{
// save current RECT
pRects[ pRgnData->nCount++ ] = CRect( first, i, j, i + 1 );
// if buffer full reallocate it with more room
if ( pRgnData->nCount >= dwRectsCount )
{
dwRectsCount += ADD_RECTS_COUNT;
// allocate new buffer
LPBYTE pRgnDataNew = new BYTE[ RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) ];
// copy current region data to it
memcpy( pRgnDataNew, pRgnData, RGNDATAHEADER_SIZE + pRgnData->nCount * sizeof(RECT) );
// delte old region data buffer
delete pRgnData;
// set pointer to new regiondata buffer to current
pRgnData = (RGNDATAHEADER*)pRgnDataNew;
// correct pointer to RECT table
pRects = (LPRECT)((LPBYTE)pRgnData + RGNDATAHEADER_SIZE);
}
wasfirst = false;
}
pColor -= dwLineBackLen;
}
// release image data
delete pBits;
delete bi;
// create region
HRGN hRgn = ExtCreateRegion( NULL, RGNDATAHEADER_SIZE + pRgnData->nCount * sizeof(RECT), (LPRGNDATA)pRgnData );
// release region data
delete pRgnData;
return hRgn;
}
BOOL CImageLoader::DrawImage(CEnBitmap &bmp, int nX, int nY, int nCol, int nRow)
{
nX -= 1;
nY -= 1;
int w = GetWidth()/nCol;
int h = GetHeight()/nRow;
HBITMAP hOldBmp;
CDC memDC;
CClientDC dc(0);
memDC.CreateCompatibleDC(dc.m_hDC);
bmp.CreateCompatibleBitmap(dc.m_hDC, w, h);
hOldBmp = memDC.SelectBitmap(bmp.m_hBitmap);
StretchDraw( &memDC, CRect( 0, 0, w, h ),
CRect(GetWidth()*nX/nCol, GetHeight()*nY/nRow, GetWidth()*nX/nCol+w ,GetHeight()*nY/nRow+h ) );
memDC.SelectBitmap(hOldBmp);
//dc.DeleteDC();
memDC.DeleteDC();
::DeleteObject(hOldBmp);
hOldBmp = NULL;
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
///
/// @param [in] pDC Device context
/// @param [in] x
/// @param [in] y
/// @param [in] rect
/// @param [in] state Button state
/// - 0 : Normal
/// - 1 : Pressed
/// - 2 : Hover
/// - 3 : Disabled
/// @param [in] clrTrans
/// @param [in] bTrans
///
//////////////////////////////////////////////////////////////////////////
BOOL CImageLoader::DrawImageByIndex(CDC* pDC, CRect rect, int nIndex, COLORREF clrTrans, BOOL bTrans)
{
if(m_hBitmap == NULL) return FALSE;
Draw(pDC, rect.left, rect.top, CRect(nIndex*rect.Width(), 0, (nIndex+1)*rect.Width(), GetHeight()), clrTrans, bTrans);
return TRUE;
}