www.pudn.com > VolumeBar.rar > BitmapSlider.cpp


// BitmapSlider.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "BitmapSlider.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// 
// CBitmapSlider v1.5 
// 
// It's free for everywhere - 16/September/2003 - Joon-ho Ryu 
// 
///////////////////////////////////////////////////////////////////////////// 
 
 
CBitmapSlider::CBitmapSlider() 
{ 
	m_nPos = m_nMin = 0; 
	m_nMax = 100; 
	m_nPage = 20; 
 
	m_nMarginLeft = m_nMarginRight = m_nMarginTop = m_nMarginBottom = 0; 
	m_nThumbWidth = m_nThumbHeight = 0; 
 
	m_bChannel = m_bVertical = m_bThumb = m_bLButtonDown = FALSE; 
 
	m_bFocusRect = m_bFocus = FALSE; 
	m_bDrawFocusRect = TRUE; 
 
	m_bEnable = TRUE; 
 
	m_nThumbBgX = m_nThumbBgY = -1; 
} 
 
CBitmapSlider::~CBitmapSlider() 
{ 
} 
 
 
BEGIN_MESSAGE_MAP(CBitmapSlider, CStatic) 
	//{{AFX_MSG_MAP(CBitmapSlider) 
	ON_WM_ERASEBKGND() 
	ON_WM_PAINT() 
	ON_WM_LBUTTONDOWN() 
	ON_WM_MOUSEMOVE() 
	ON_WM_LBUTTONUP() 
	ON_WM_GETDLGCODE() 
	ON_WM_KEYDOWN() 
	ON_WM_KILLFOCUS() 
	ON_WM_SETFOCUS() 
	ON_WM_CREATE() 
	ON_WM_DESTROY() 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CBitmapSlider message handlers 
 
BOOL CBitmapSlider::OnEraseBkgnd(CDC* pDC)  
{	 
	// Do not erase background for the transparency effect 
	return TRUE; 
} 
 
// Draw channel and thumb 
// 
void CBitmapSlider::OnPaint()  
{ 
	CPaintDC dcOrigin(this); 
 
	// "Flicker Free Drawing In MFC" by Keith Rule 
	CMemDC dc( &dcOrigin, &m_rect, m_bTransparentChannel ); 
 
	CDC dcMem; 
	dcMem.CreateCompatibleDC( &dc ); 
 
	CBitmap *pbmTmp; 
 
	// Delete focus rectangle for transparent channel 
	if( m_bFocusRect && ( m_bTransparentChannel || !m_bChannel ) ) { 
 
		dc.DrawFocusRect( m_rect ); 
		m_bFocusRect = FALSE; 
	} 
 
	// Draw channel 
	if( m_bChannel ) { 
 
		pbmTmp = dcMem.SelectObject( &m_bmChannel ); 
 
		// There is a bitmap for active channel 
		if( m_bChannelActive && m_bEnable ) { 
 
			// Vertical slider 
			if( m_bVertical ) { 
 
				// Lower part 
				DrawBitmap( &dc, 0, Pos2Pixel(m_nPos), 
					m_nWidth, m_nHeight - Pos2Pixel(m_nPos), 
					&dcMem, 0, Pos2Pixel(m_nPos), 
					&m_bmChannelActiveMask, m_bTransparentChannel ); 
 
				dcMem.SelectObject( &m_bmChannelActive ); 
 
				// Upper part 
				DrawBitmap( &dc, 0, 0, m_nWidth, Pos2Pixel(m_nPos), 
					&dcMem, 0, 0, &m_bmChannelMask, m_bTransparentChannel ); 
 
			// Horizontal slider 
			} else { 
 
				// Right side 
				DrawBitmap( &dc, Pos2Pixel(m_nPos), 0, 
					m_nWidth - Pos2Pixel(m_nPos), m_nHeight, 
					&dcMem, Pos2Pixel(m_nPos), 0,  
					&m_bmChannelActiveMask, m_bTransparentChannel ); 
 
				dcMem.SelectObject( &m_bmChannelActive ); 
 
				// Left side 
				DrawBitmap( &dc, 0, 0, Pos2Pixel(m_nPos), m_nHeight, 
					&dcMem, 0, 0, &m_bmChannelMask, m_bTransparentChannel ); 
			} 
 
		// Only one bitmap for channel 
		} else { 
 
			DrawBitmap( &dc, 0, 0, m_nWidth, m_nHeight, 
				&dcMem, 0, 0, &m_bmChannelMask, m_bTransparentChannel ); 
 
		} 
 
		dcMem.SelectObject( pbmTmp ); 
	} 
 
	// If there is a bitmap to restore background image of a thumb 
	if( m_nThumbBgX != -1 ) { 
 
		RestoreBackground( 
			&dc, m_nThumbBgX, m_nThumbBgY, 
			m_nThumbWidth, m_nThumbHeight, &m_bmThumbBg ); 
 
		m_nThumbBgX = -1; 
	} 
 
	// Draw thumb 
	if( m_bThumb && m_bEnable ) { 
 
		if( m_bThumbActive && m_bLButtonDown ) 
			pbmTmp = dcMem.SelectObject( &m_bmThumbActive ); // Active thumb 
		else 
			pbmTmp = dcMem.SelectObject( &m_bmThumb ); // Normal thumb 
 
		// Vertical slider 
		if( m_bVertical ) { 
 
			// Background image is need to be restored 
			if( m_bTransparentChannel || !m_bChannel ) { 
 
				m_nThumbBgX = m_nMarginLeft; 
				m_nThumbBgY = Pos2Pixel(m_nPos) - m_nThumbHeight/2; 
 
				CopyBackground( 
					&dc, m_nThumbBgX, m_nThumbBgY, 
					m_nThumbWidth, m_nThumbHeight, &m_bmThumbBg ); 
			} 
 
			DrawBitmap( 
				&dc, m_nMarginLeft, Pos2Pixel(m_nPos) - m_nThumbHeight/2, 
				m_nThumbWidth, m_nThumbHeight, 
				&dcMem, 0, 0, &m_bmThumbMask, m_bTransparentThumb ); 
 
		// Horizontal slider 
		} else { 
 
			// Background image is need to be restored 
			if( m_bTransparentChannel || !m_bChannel ) { 
 
				m_nThumbBgX = Pos2Pixel(m_nPos) - m_nThumbWidth/2; 
				m_nThumbBgY = m_nMarginTop; 
 
				CopyBackground( 
					&dc, m_nThumbBgX, m_nThumbBgY, 
					m_nThumbWidth, m_nThumbHeight, &m_bmThumbBg ); 
			} 
 
			DrawBitmap( 
				&dc, Pos2Pixel(m_nPos) - m_nThumbWidth/2, m_nMarginTop, 
				m_nThumbWidth, m_nThumbHeight, 
				&dcMem, 0, 0, &m_bmThumbMask, m_bTransparentThumb ); 
 
		} // if horizontal 
 
		dcMem.SelectObject( pbmTmp ); 
 
	} // if draw thumb 
 
	// Draw focus rectangle 
	if( m_bDrawFocusRect && m_bFocus && m_bEnable ) { 
 
		dc.DrawFocusRect( m_rect ); 
		m_bFocusRect = TRUE; 
	} 
 
	dcMem.DeleteDC(); 
} 
 
// Sets the maximum range for the slider. 
// 
// Parameters: 
//		[IN]	nMax 
//				Maximum position for the slider. 
//		[IN]	bRedraw 
//				TRUE to redraw after the range is set. 
//				FALSE to only change maximum position. 
// 
void CBitmapSlider::SetRangeMax(int nMax, BOOL bRedraw) 
{ 
	m_nMax = nMax; 
	if( bRedraw ) 
		Invalidate(); 
} 
 
// Sets the minimum range for the slider. 
// 
// Parameters: 
//		[IN]	nMin 
//				Minimum position for the slider. 
//		[IN]	bRedraw 
//				TRUE to redraw after the range is set. 
//				FALSE to only change minimum position. 
// 
void CBitmapSlider::SetRangeMin(int nMin, BOOL bRedraw) 
{ 
	m_nMin = nMin; 
	if( bRedraw ) 
		Invalidate(); 
} 
 
// Sets the range (minimum and maximum positions) for the slider. 
// 
// Parameters: 
//		[IN]	nMin 
//				Minimum position for the slider. 
//		[IN]	nMax 
//				Maximum position for the slider. 
//		[IN]	bRedraw 
//				TRUE to redraw after the range is set. 
//				FALSE to only change the range. 
// 
void CBitmapSlider::SetRange(int nMin, int nMax, BOOL bRedraw) 
{ 
	SetRangeMin( nMin, FALSE ); 
	SetRangeMax( nMax, bRedraw ); 
} 
 
// Sets the current position of the slider. 
// 
// Parameters: 
//		[IN]	nPos 
//				Specifies the new slider position. 
// 
void CBitmapSlider::SetPos(int nPos) 
{ 
	m_nPos = nPos; 
 
	// Boundary check 
	if( m_nPos > m_nMax ) 
		m_nPos = m_nMax; 
	if( m_nPos < m_nMin ) 
		m_nPos = m_nMin; 
 
	Invalidate(); 
} 
 
// Sets the size of the page for a control. 
// 
// Parameters: 
//		[IN]	nSize 
//				The new page size of the control. 
// 
// Return value: 
//		The previous page size. 
// 
int CBitmapSlider::SetPageSize(int nSize) 
{ 
	int nRet = m_nPage; 
 
	m_nPage = nSize; 
 
	return nRet; 
} 
 
// Sets the left, top, right, and bottom margins for a control 
// 
void CBitmapSlider::SetMargin(int nLeft, int nTop, int nRight, int nBottom ) 
{ 
	SetMarginLeft( nLeft ); 
	SetMarginTop( nTop ); 
	SetMarginRight( nRight ); 
	SetMarginBottom( nBottom ); 
} 
 
// Enables or disables control. 
// 
//		[IN]	bEnable 
//				TRUE to enable control. 
//				FALSE to disable control. 
// 
void CBitmapSlider::Enable(BOOL bEnable) 
{ 
	m_bEnable = bEnable; 
 
	// If control is disabled during dragging 
	if( !m_bEnable && m_bLButtonDown ) { 
 
		m_bLButtonDown = FALSE; 
		ReleaseCapture(); 
	} 
 
	Invalidate(); 
} 
 
// Specify whether draw focus rectangle or not. 
// 
//		[IN]	bDraw 
//				TRUE to draw focus rectangle. 
//				FALSE to hide focus rectangle. 
// 
//		[IN]	bRedraw 
//				TRUE to redraw status is changed. 
//				FALSE to only change the status. 
// 
void CBitmapSlider::DrawFocusRect(BOOL bDraw, BOOL bRedraw) 
{ 
	m_bDrawFocusRect = bDraw; 
 
	if( bRedraw ) 
		Invalidate(); 
} 
 
// Load bitmaps for a channel 
// 
// Parameters: 
//		[IN]	nChannelID 
//				ID number of the bitmap resource of the channel. 
//		[IN]	nActiveID 
//				ID number of the bitmap resource of the active channel. 
//		[IN]	bTransparent 
//				TRUE to apply transparency effect. 
//				FALSE to display normal bitmap. 
//		[IN]	clrpTransColor 
//				RGB color to treat as transparent. 
//		[IN]	iTransPixelX 
//				Logical x-coordinate of a point. 
//				It's color will be treated as transparent. 
//		[IN]	iTransPixelY 
//				Logical y-coordinate of a point. 
//				It's color will be treated as transparent. 
// 
// Return value: 
//		TRUE 
//			Function succeedes. 
//		FALSE 
//			Function failes to load bitmaps. 
// 
BOOL CBitmapSlider::SetBitmapChannel( 
	UINT nChannelID, UINT nActiveID , BOOL bTransparent, 
	COLORREF clrpTransColor, int iTransPixelX, int iTransPixelY ) 
{ 
	// This control will not have any bitmap for channel 
	if( !nChannelID ) { 
 
		m_bChannel = FALSE; 
 
		m_bmChannel.DeleteObject(); 
		m_bmChannelMask.DeleteObject(); 
		m_bmChannelActive.DeleteObject(); 
		m_bmChannelActiveMask.DeleteObject(); 
	 
		return TRUE; 
	} 
 
	// load a bitmap 
	m_bmChannel.DeleteObject(); 
 
	if( !m_bmChannel.LoadBitmap( nChannelID ) ) 
		return FALSE; 
 
	// Prepare mask for transparency effect. 
	if( bTransparent ) { 
 
		PrepareMask( &m_bmChannel, &m_bmChannelMask, 
			clrpTransColor, iTransPixelX, iTransPixelY ); 
	} 
 
	// Load a bitmap for active state. 
	if( nActiveID ) { 
 
		m_bmChannelActive.DeleteObject(); 
 
		if( !m_bmChannelActive.LoadBitmap( nActiveID ) ) { 
 
			m_bmChannel.DeleteObject(); 
			if( bTransparent ) 
				m_bmChannelMask.DeleteObject(); 
 
			return FALSE; 
		} 
 
		if( bTransparent ) { 
 
			PrepareMask( &m_bmChannelActive, &m_bmChannelActiveMask, 
				clrpTransColor, iTransPixelX, iTransPixelY ); 
		} 
		 
		m_bChannelActive = TRUE; 
 
	// There is no bitmap for active state. 
	} else 
		m_bChannelActive = FALSE; 
 
	// Get size of bitmap. 
	BITMAP	bitmap; 
	m_bmChannel.GetBitmap( &bitmap ); 
 
	m_nWidth = bitmap.bmWidth; 
	m_nHeight = bitmap.bmHeight; 
 
	// Compare size 
	if( m_bChannelActive ) { 
 
		BITMAP	bitmap; 
		m_bmChannelActive.GetBitmap( &bitmap ); 
 
		ASSERT( m_nWidth == bitmap.bmWidth && m_nHeight == bitmap.bmHeight ); 
	} 
 
	// Change size of control as same as the bitmap. 
	SetWindowPos(NULL, 0, 0, m_nWidth, m_nHeight, SWP_NOZORDER | SWP_NOMOVE); 
 
	GetClientRect( &m_rect ); 
 
	m_bTransparentChannel = bTransparent; 
	m_bChannel = TRUE; 
 
	return TRUE; 
} 
 
// Load bitmaps for a thumb 
// 
// Parameters: 
//		[IN]	nThumbID 
//				ID number of the bitmap resource of the thumb 
//		[IN]	nActiveID 
//				ID number of the bitmap resource of the active thumb 
//		[IN]	bTransparent 
//				TRUE to apply transparency effect 
//				FALSE to display normal bitmap 
//		[IN]	clrpTransColor 
//				RGB color to treat as transparent 
//		[IN]	iTransPixelX 
//				Logical x-coordinate of a point. 
//				It's color will be treated as transparent 
//		[IN]	iTransPixelY 
//				Logical y-coordinate of a point. 
//				It's color will be treated as transparent 
// 
// Return value: 
//		TRUE 
//			Function succeedes. 
//		FALSE 
//			Function failes to load bitmaps. 
// 
BOOL CBitmapSlider::SetBitmapThumb( 
	UINT nThumbID, UINT nActiveID, BOOL bTransparent, 
	COLORREF clrpTransColor, int iTransPixelX, int iTransPixelY ) 
{ 
	// This control will not have bitmap 
	if( !nThumbID ) { 
 
		m_bThumb = FALSE; 
 
		m_bmThumb.DeleteObject(); 
		m_bmThumbMask.DeleteObject(); 
		m_bmThumbActive.DeleteObject(); 
		m_bmThumbActiveMask.DeleteObject(); 
		m_bmThumbBg.DeleteObject(); 
 
		return TRUE; 
	} 
 
	// load a bitmap 
	m_bmThumb.DeleteObject(); 
 
	if( !m_bmThumb.LoadBitmap( nThumbID ) ) 
		return FALSE; 
 
	// Prepare mask for transparency effect. 
	if( bTransparent ) { 
 
		PrepareMask( &m_bmThumb, &m_bmThumbMask, 
			clrpTransColor, iTransPixelX, iTransPixelY ); 
	} 
 
	// Load a bitmap for active state. 
	if( nActiveID ) { 
 
		m_bmThumbActive.DeleteObject(); 
 
		if( !m_bmThumbActive.LoadBitmap( nActiveID ) ) { 
 
			m_bmThumb.DeleteObject(); 
			if( bTransparent ) 
				m_bmThumbMask.DeleteObject(); 
 
			return FALSE; 
		} 
 
		if( bTransparent ) { 
 
			PrepareMask( &m_bmThumbActive, &m_bmThumbActiveMask, 
				clrpTransColor, iTransPixelX, iTransPixelY ); 
		} 
		 
		m_bThumbActive = TRUE; 
 
	// There is no bitmap for active state. 
	} else 
		m_bThumbActive = FALSE; 
 
	// Get size of the bitmap 
	BITMAP	bitmap; 
	m_bmThumb.GetBitmap( &bitmap ); 
 
	m_nThumbWidth = bitmap.bmWidth; 
	m_nThumbHeight = bitmap.bmHeight; 
 
	// Get size of the control if there was no bitmap for channel. 
	if( !m_bChannel ) { 
 
		GetClientRect( &m_rect ); 
		m_nHeight = m_rect.Height(); 
		m_nWidth = m_rect.Width(); 
	} 
 
	ASSERT( m_nThumbWidth <= m_nWidth && m_nThumbHeight <= m_nHeight ); 
 
	// Compare size 
	if( m_bThumbActive ) { 
 
		BITMAP	bitmap; 
		m_bmThumbActive.GetBitmap( &bitmap ); 
 
		ASSERT( 
			m_nThumbWidth == bitmap.bmWidth && 
			m_nThumbHeight == bitmap.bmHeight ); 
	} 
 
	// Set attributes 
	m_bTransparentThumb = bTransparent; 
	m_bThumb = TRUE; 
 
	return TRUE; 
} 
 
// OnLButtonDown 
// 
// Dragging is started 
// 
void CBitmapSlider::OnLButtonDown(UINT nFlags, CPoint point)  
{ 
	if( !m_bEnable ) 
		return; 
 
	SetCapture(); 
	SetFocus(); 
 
	m_bLButtonDown = TRUE; 
 
	// If mouse button is clicked on the thumb, 
	// capture the coordinates of mouse pointer and center of thumb 
	// and calculate distance between them. 
	if( m_bVertical ) { 
 
		if( abs( point.y - Pos2Pixel( m_nPos ) ) <= m_nThumbHeight / 2 ) 
			m_nMouseOffset = point.y - Pos2Pixel( m_nPos ); 
		else 
			m_nMouseOffset = 0; 
 
	} else { 
 
		if( abs( point.x - Pos2Pixel( m_nPos ) ) <= m_nThumbWidth / 2 ) 
			m_nMouseOffset = point.x - Pos2Pixel( m_nPos ); 
		else 
			m_nMouseOffset = 0; 
	} 
 
	OnMouseMove( nFlags, point ); 
	Invalidate(); 
 
	CStatic::OnLButtonDown(nFlags, point); 
} 
 
// OnMouseMove 
// 
// During dragging 
// 
void CBitmapSlider::OnMouseMove(UINT nFlags, CPoint point)  
{ 
	if( !m_bLButtonDown || !m_bEnable ) 
		return; 
 
	int nPixel; 
 
	// Boundary check 
	if( m_bVertical ) { 
 
		nPixel = point.y - m_nMouseOffset; 
 
		if( nPixel > m_nHeight - m_nMarginBottom - m_nThumbHeight/2 ) 
			nPixel = m_nHeight - m_nMarginBottom - m_nThumbHeight/2; 
 
		if( nPixel < m_nMarginTop + m_nThumbHeight/2 ) 
			nPixel = m_nMarginTop + m_nThumbHeight/2; 
 
	} else { 
 
		nPixel = point.x - m_nMouseOffset; 
 
		if( nPixel < m_nMarginLeft + m_nThumbWidth/2 ) 
			nPixel = m_nMarginLeft + m_nThumbWidth/2; 
 
		if( nPixel > m_nWidth - m_nMarginRight - m_nThumbWidth/2 ) 
			nPixel = m_nWidth - m_nMarginRight - m_nThumbWidth/2; 
	} 
 
	// Apply change 
	if( Pos2Pixel(m_nPos) != nPixel ) { 
 
		SetPos( Pixel2Pos( nPixel ) ); 
 
		::PostMessage( 
			GetParent()->GetSafeHwnd(), WM_BITMAPSLIDER_MOVING, 
			GetDlgCtrlID(), m_nPos ); 
	} 
 
	CStatic::OnMouseMove(nFlags, point); 
} 
 
// OnLButtonUp 
// 
// Dragging is finished 
// 
void CBitmapSlider::OnLButtonUp(UINT nFlags, CPoint point)  
{ 
	if( !m_bEnable ) 
		return; 
 
	ReleaseCapture(); 
	m_bLButtonDown = FALSE; 
 
	Invalidate(); 
 
	::PostMessage( 
		GetParent()->GetSafeHwnd(),	WM_BITMAPSLIDER_MOVED, 
		GetDlgCtrlID(), m_nPos ); 
 
	CStatic::OnLButtonUp(nFlags, point); 
} 
 
// Calculate point of thumb from position value 
// 
int CBitmapSlider::Pos2Pixel(int nPos) 
{ 
	if( m_bVertical ) { 
 
		return 
			m_nMarginTop + m_nThumbHeight/2 + 
			(int)( 
			( m_nHeight - m_nMarginTop - m_nMarginBottom - m_nThumbHeight ) * 
			((double) ( nPos - m_nMin ) / ( m_nMax - m_nMin ) ) 
			); 
 
	} else { 
 
		return (int)( 
			( m_nWidth - m_nMarginLeft - m_nMarginRight - m_nThumbWidth ) * 
			((double) ( nPos - m_nMin ) / ( m_nMax - m_nMin ) ) 
			) + m_nMarginLeft + m_nThumbWidth/2; 
	} 
} 
 
// Calculate position value from point of mouse 
// 
int CBitmapSlider::Pixel2Pos(int nPixel) 
{ 
	if( m_bVertical ) { 
 
		return (int)( 
			m_nMin + 
			(double)( nPixel - m_nMarginTop - m_nThumbHeight/2) / 
			( m_nHeight - m_nMarginBottom - m_nMarginTop - m_nThumbHeight ) * 
			( m_nMax - m_nMin ) 
			); 
 
	} else { 
 
		return (int)( 
			m_nMin + 
			(double)( nPixel - m_nMarginLeft - m_nThumbWidth/2 ) / 
			( m_nWidth - m_nMarginLeft - m_nMarginRight - m_nThumbWidth ) * 
			( m_nMax - m_nMin ) 
			); 
	} 
} 
 
// Copy background image to bitmap 
// 
void CBitmapSlider::CopyBackground( 
	CDC *pDC, int nXSrc, int nYSrc, int nWidth, int nHeight, CBitmap *pBmDst) 
{ 
	pBmDst->DeleteObject(); 
	pBmDst->CreateCompatibleBitmap( pDC, nWidth, nHeight ); 
 
	CDC memDC; 
 
	memDC.CreateCompatibleDC( pDC ); 
	CBitmap *pBmTmp = memDC.SelectObject( pBmDst ); 
 
	memDC.BitBlt( 0, 0, nWidth, nHeight, pDC, nXSrc, nYSrc, SRCCOPY ); 
 
	memDC.SelectObject( pBmTmp ); 
	memDC.DeleteDC(); 
} 
 
// Restore background image from bitmap 
// 
void CBitmapSlider::RestoreBackground( 
	CDC *pDC, int nXDst, int nYDst, int nWidth, int nHeight, CBitmap *pBmSrc) 
{ 
	CDC memDC; 
 
	memDC.CreateCompatibleDC( pDC ); 
	CBitmap *pBmTmp = memDC.SelectObject( pBmSrc ); 
 
	pDC->BitBlt( nXDst, nYDst, nWidth, nHeight, &memDC, 0, 0, SRCCOPY ); 
 
	memDC.SelectObject( pBmTmp ); 
	memDC.DeleteDC(); 
} 
 
// DrawBitmap 
// 
// It's for code readability 
// 
void CBitmapSlider::DrawBitmap( 
	CDC *pDC, int xStart, int yStart, int wWidth, int wHeight, 
	CDC *pTmpDC, int xSource, int ySource, CBitmap *bmMask, BOOL bTransparent ) 
{ 
	if( bTransparent ) { 
 
		DrawTransparentBitmap( 
			pDC, xStart, yStart, 
			wWidth, wHeight, 
			pTmpDC, xSource, ySource, bmMask ); 
 
	} else { 
 
		pDC->BitBlt( xStart, yStart, 
			wWidth, wHeight, 
			pTmpDC, xSource, ySource, SRCCOPY ); 
	} 
} 
 
// PrepareMask 
// 
// "Drawing Transparent Bitmap with ease with on the fly masks in MFC" 
// By Raja Segar 
// 
// I changed default clrpTransColor value from NULL(black) to 0xFF000000(not RGB color) 
// 
void CBitmapSlider::PrepareMask( 
	CBitmap *pBmpSource, CBitmap *pBmpMask, 
	COLORREF clrpTransColor, int iTransPixelX, int iTransPixelY) 
{ 
	BITMAP bm; 
 
	// Get the dimensions of the source bitmap 
	pBmpSource->GetObject(sizeof(BITMAP), &bm); 
 
	// Create the mask bitmap 
	pBmpMask->DeleteObject(); 
	pBmpMask->CreateBitmap( bm.bmWidth, bm.bmHeight, 1, 1, NULL); 
 
	// We will need two DCs to work with. One to hold the Image 
	// (the source), and one to hold the mask (destination). 
	// When blitting onto a monochrome bitmap from a color, pixels 
	// in the source color bitmap that are equal to the background 
	// color are blitted as white. All the remaining pixels are 
	// blitted as black. 
 
	CDC hdcSrc, hdcDst; 
 
	hdcSrc.CreateCompatibleDC(NULL); 
	hdcDst.CreateCompatibleDC(NULL); 
 
	// Load the bitmaps into memory DC 
	CBitmap* hbmSrcT = (CBitmap*) hdcSrc.SelectObject(pBmpSource); 
	CBitmap* hbmDstT = (CBitmap*) hdcDst.SelectObject(pBmpMask); 
 
	// Dynamically get the transparent color 
	COLORREF clrTrans; 
	if (clrpTransColor == 0xFF000000) 
	{ 
		// User did not specify trans color so get it from bmp 
		clrTrans = hdcSrc.GetPixel(iTransPixelX, iTransPixelY); 
	} 
	else 
	{ 
		clrTrans = clrpTransColor; 
	} 
 
 
	// Change the background to trans color 
	COLORREF clrSaveBk  = hdcSrc.SetBkColor(clrTrans); 
 
	// This call sets up the mask bitmap. 
	hdcDst.BitBlt(0,0,bm.bmWidth, bm.bmHeight, &hdcSrc,0,0,SRCCOPY); 
 
	// Now, we need to paint onto the original image, making 
	// sure that the "transparent" area is set to black. What 
	// we do is AND the monochrome image onto the color Image 
	// first. When blitting from mono to color, the monochrome 
	// pixel is first transformed as follows: 
	// if  1 (black) it is mapped to the color set by SetTextColor(). 
	// if  0 (white) is is mapped to the color set by SetBkColor(). 
	// Only then is the raster operation performed. 
 
	COLORREF clrSaveDstText = hdcSrc.SetTextColor(RGB(255,255,255)); 
	hdcSrc.SetBkColor(RGB(0,0,0)); 
 
	hdcSrc.BitBlt(0,0,bm.bmWidth, bm.bmHeight, &hdcDst,0,0,SRCAND); 
 
	// Clean up by deselecting any objects, and delete the 
	// DC's. 
	hdcDst.SetTextColor(clrSaveDstText); 
 
	hdcSrc.SetBkColor(clrSaveBk); 
	hdcSrc.SelectObject(hbmSrcT); 
	hdcDst.SelectObject(hbmDstT); 
 
	hdcSrc.DeleteDC(); 
	hdcDst.DeleteDC(); 
} 
 
// DrawTransparentBitmap 
// 
// "Drawing Transparent Bitmap with ease with on the fly masks in MFC" 
// By Raja Segar 
// 
void CBitmapSlider::DrawTransparentBitmap( 
	CDC *pDC, int xStart, int yStart, int wWidth, int wHeight, 
	CDC *pTmpDC, int xSource, int ySource, CBitmap *bmMask ) 
{ 
	// We are going to paint the two DDB's in sequence to the destination. 
	// 1st the monochrome bitmap will be blitted using an AND operation to 
	// cut a hole in the destination. The color image will then be ORed 
	// with the destination, filling it into the hole, but leaving the 
	// surrounding area untouched. 
 
	CDC hdcMem; 
	hdcMem.CreateCompatibleDC(NULL); 
 
	CBitmap* hbmT = hdcMem.SelectObject(bmMask); 
 
	pDC->BitBlt( xStart, yStart, wWidth, wHeight, &hdcMem, 
		xSource, ySource, SRCAND); 
 
	// Also note the use of SRCPAINT rather than SRCCOPY. 
 
	pDC->BitBlt(xStart, yStart, wWidth, wHeight, pTmpDC, 
		xSource, ySource,SRCPAINT); 
 
	// Now, clean up. 
	hdcMem.SelectObject(hbmT); 
	hdcMem.DeleteDC(); 
} 
 
// To get keyboard input 
// 
UINT CBitmapSlider::OnGetDlgCode()  
{ 
	if( GetKeyState(VK_TAB) >= 0 ) { 
 
		return  DLGC_WANTALLKEYS; 
	} 
	 
	return CStatic::OnGetDlgCode(); 
} 
 
// Handling keyboard input 
// 
void CBitmapSlider::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)  
{ 
	if( !m_bEnable ) 
		return; 
 
	switch( nChar ) { 
 
	// Left & up 
	case VK_LEFT : 
	case VK_UP : 
 
		SetPos( m_nPos-1 ); 
		break; 
 
	// Right & down 
	case VK_RIGHT : 
	case VK_DOWN : 
 
		SetPos( m_nPos+1 ); 
		break; 
 
	// Home 
	case VK_HOME : 
 
		SetPos( m_nMin ); 
		break; 
 
	// End 
	case VK_END : 
 
		SetPos( m_nMax ); 
		break; 
 
	// Page up 
	case VK_PRIOR : 
 
		SetPos( m_nPos - m_nPage ); 
		break; 
 
	// Page down 
	case VK_NEXT : 
 
		SetPos( m_nPos + m_nPage ); 
		break; 
 
	default : 
 
		CStatic::OnKeyDown(nChar, nRepCnt, nFlags); 
		return; 
	} 
	 
	::PostMessage( 
		GetParent()->GetSafeHwnd(),	WM_BITMAPSLIDER_MOVED, 
		GetDlgCtrlID(), m_nPos ); 
 
	CStatic::OnKeyDown(nChar, nRepCnt, nFlags); 
} 
 
// Control looses its focus 
// 
void CBitmapSlider::OnKillFocus(CWnd* pNewWnd)  
{ 
	CStatic::OnKillFocus(pNewWnd); 
 
	m_bFocus = FALSE; 
	Invalidate(); 
} 
 
// This control gains its focus 
// 
void CBitmapSlider::OnSetFocus(CWnd* pOldWnd)  
{ 
	CStatic::OnSetFocus(pOldWnd); 
 
	m_bFocus = TRUE; 
	Invalidate(); 
} 
 
// Release resources 
// 
void CBitmapSlider::OnDestroy()  
{ 
	CStatic::OnDestroy(); 
	 
	m_bmThumb.DeleteObject(); 
	m_bmThumbMask.DeleteObject(); 
 
	m_bmThumbActive.DeleteObject(); 
	m_bmThumbActiveMask.DeleteObject(); 
 
	m_bmThumbBg.DeleteObject(); 
 
	m_bmChannel.DeleteObject(); 
	m_bmChannelMask.DeleteObject(); 
 
	m_bmChannelActive.DeleteObject(); 
	m_bmChannelActiveMask.DeleteObject(); 
}