#pragma once #include "..//..//DCBuffer.h" #include "..//..//COM_IMAGE.h" #define WM_BITMAPSLIDER_MOVING WM_USER + 9425 #define WM_BITMAPSLIDER_MOVED WM_USER + 9426 class CImgSliderDEx: public CStatic { // Construction public: CImgSliderDEx(); virtual ~CImgSliderDEx(); // Implementation public: BOOL Init(CString strChannelPath, CString strChannelActivePath, CString strPath, CString strActivePath); void GetRange( int &nMin, int &nMax ) { nMin = m_nMin; nMax = m_nMax; }; void SetRange( int nMin, int nMax, BOOL bRedraw=FALSE ); int GetPos() { return m_nPos; }; void SetPos( int nPos ); int SetPageSize( int nSize ); void Enable( BOOL bEnable = TRUE ); void SetVerticalSlider(){m_bVertical = TRUE;} protected: void DrawFocusRect( BOOL bDraw = TRUE, BOOL bRedraw = FALSE ); void ResetBG( ) {m_nThumbBgX = -1;} BOOL SetBitmapChannel(CString strPath, CString strActivePath = L""); BOOL SetImgThumb(CString strPath, CString strActivePath = L""); void DrawImg( CDC* pDC, int xStart, int yStart, int wWidth, int wHeight, COM_IMAGE* pImg, int xSource, int ySource); int Pixel2Pos( int nPixel ); int Pos2Pixel( int nPos ); void SetMargin( int nLeft, int nTop, int nRight, int nBottom ); CRect m_rect; int m_nWidth, m_nHeight; int m_nChannelWidth, m_nChannelHeight; int m_nActiveWidth, m_nActiveHeight; int m_nThumbWidth, m_nThumbHeight; int m_nMax, m_nMin, m_nPos, m_nPage; int m_nMarginLeft, m_nMarginRight, m_nMarginTop, m_nMarginBottom; int m_nThumbBgX, m_nThumbBgY; int m_nMouseOffset; BOOL m_bVertical; BOOL m_bChannelActive, m_bThumbActive; BOOL m_bThumb, m_bChannel; BOOL m_bLButtonDown, m_bFocus, m_bFocusRect, m_bDrawFocusRect; BOOL m_bEnable; COM_IMAGE m_imgChannel, m_imgChannelActive; COM_IMAGE m_imgThumb, m_imgActive; //{{AFX_MSG(CImgSliderDEx) afx_msg BOOL OnEraseBkgnd(CDC* pDC); afx_msg void OnPaint(); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnMouseMove(UINT nFlags, CPoint point); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); afx_msg UINT OnGetDlgCode(); afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg void OnKillFocus(CWnd* pNewWnd); afx_msg void OnSetFocus(CWnd* pOldWnd); afx_msg void OnDestroy(); //}}AFX_MSG DECLARE_MESSAGE_MAP() };
/
// BitmapSlider.cpp : implementation file
//
#include "stdafx.h"
#include "ImgSliderDEx.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CImgSliderDEx::CImgSliderDEx()
{
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;
}
CImgSliderDEx::~CImgSliderDEx()
{
}
BEGIN_MESSAGE_MAP(CImgSliderDEx, CStatic)
//{{AFX_MSG_MAP(CImgSliderDEx)
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()
/
// CImgSliderDEx message handlers
BOOL CImgSliderDEx::Init(CString strChannelPath, CString strChannelActivePath, CString strPath, CString strActivePath)
{
if( SetBitmapChannel(strChannelPath,strChannelActivePath)
&& SetImgThumb(strPath,strActivePath))
return TRUE;
return FALSE;
}
BOOL CImgSliderDEx::OnEraseBkgnd(CDC* pDC)
{
// Do not erase background for the transparency effect
return TRUE;
}
// Draw channel and thumb
//
void CImgSliderDEx::OnPaint()
{
CPaintDC dcOrigin(this);
CDCBuffer dc(&dcOrigin, &m_rect);
// Delete focus rectangle for transparent channel
if( m_bFocusRect && !m_bChannel )
{
dc.DrawFocusRect( m_rect );
m_bFocusRect = FALSE;
}
// Draw channel
if( m_bChannel )
{
if( m_bChannelActive && m_bEnable )
{
int iDestRatePos = Pos2Pixel(m_nPos);
int iSourceRatePos = 0;
if( m_bVertical )
{
iSourceRatePos = iDestRatePos*m_nChannelHeight/m_nHeight;
m_imgChannel.drawImage(&dc,
CRect(0, iDestRatePos, m_nWidth, m_nHeight),
CRect(0, 0, m_nChannelWidth, m_nChannelHeight-iSourceRatePos));
iSourceRatePos = iDestRatePos*m_nActiveHeight/m_nHeight;
m_imgChannelActive.drawImage(&dc,
CRect(0, 0, m_nWidth, iDestRatePos),
CRect(0, m_nActiveHeight-iSourceRatePos, m_nActiveWidth, m_nActiveHeight));
}
else
{
iSourceRatePos = iDestRatePos*m_nChannelWidth/m_nWidth;
m_imgChannel.drawImage(&dc,
CRect(iDestRatePos, 0, m_nWidth, m_nHeight),
CRect(iSourceRatePos, 0, m_nChannelWidth, m_nChannelHeight));
iSourceRatePos = iDestRatePos*m_nActiveWidth/m_nWidth;
m_imgChannelActive.drawImage(&dc,
CRect(0, 0, iDestRatePos, m_nHeight),
CRect(0,0, iSourceRatePos, m_nActiveHeight));
}
}
else
{
m_imgChannel.drawImage(&dc,CRect(0, 0, m_nWidth, m_nHeight),CRect(0, 0, m_nWidth, m_nHeight));
}
}
// Draw thumb
CRect rtDest(0,0,0,0);
CRect rtSource(0,0,m_nThumbWidth,m_nThumbHeight);
if( m_bVertical)
{
rtDest.left = m_nMarginLeft;
rtDest.top = Pos2Pixel(m_nPos) - m_nThumbHeight/2;
rtDest.right = m_nMarginLeft+m_nThumbWidth;
rtDest.bottom = Pos2Pixel(m_nPos) - m_nThumbHeight/2+m_nThumbHeight;
}
else
{
rtDest.left = Pos2Pixel(m_nPos) - m_nThumbWidth/2;
rtDest.top = m_nMarginTop;
rtDest.right = Pos2Pixel(m_nPos) - m_nThumbWidth/2+m_nThumbWidth;
rtDest.bottom = m_nMarginTop+m_nThumbHeight;
}
if( m_bThumb && m_bEnable )
{
if( m_bThumbActive && m_bLButtonDown )
{
m_imgActive.drawImage(&dc,rtDest,rtSource);
}
else
{
m_imgThumb.drawImage(&dc,rtDest,rtSource);
}
}
// Draw focus rectangle
if( m_bDrawFocusRect && m_bFocus && m_bEnable )
{
dc.DrawFocusRect( m_rect );
m_bFocusRect = TRUE;
}
}
// 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 CImgSliderDEx::SetRange(int nMin, int nMax, BOOL bRedraw)
{
m_nMax = nMax;
m_nMin = nMin;
if( bRedraw )
Invalidate();
}
// Sets the current position of the slider.
//
// Parameters:
// [IN] nPos
// Specifies the new slider position.
//
void CImgSliderDEx::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 CImgSliderDEx::SetPageSize(int nSize)
{
int nRet = m_nPage;
m_nPage = nSize;
return nRet;
}
// Sets the left, top, right, and bottom margins for a control
//
void CImgSliderDEx::SetMargin(int nLeft, int nTop, int nRight, int nBottom )
{
m_nMarginTop = nTop;
m_nMarginLeft = nLeft;
m_nMarginRight = nRight;
m_nMarginBottom = nBottom;
}
// Enables or disables control.
//
// [IN] bEnable
// TRUE to enable control.
// FALSE to disable control.
//
void CImgSliderDEx::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 CImgSliderDEx::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 CImgSliderDEx::SetBitmapChannel(CString strPath, CString strActivePath)
{
// load a bitmap
m_imgChannel.loadFile(strPath);
m_nChannelWidth = m_imgChannel.Width();
m_nChannelHeight = m_imgChannel.Hight();
if( L"" != strActivePath )
{
m_imgChannelActive.loadFile(strActivePath);
m_nActiveWidth = m_imgChannelActive.Width();
m_nActiveHeight = m_imgChannelActive.Hight();
m_bChannelActive = TRUE;
}
else
m_bChannelActive = FALSE;
GetClientRect( &m_rect );
m_nWidth = m_rect.Width();
m_nHeight = m_rect.Height();
m_bChannel = TRUE;
return TRUE;
}
BOOL CImgSliderDEx::SetImgThumb(CString strPath, CString strActivePath)
{
// load a bitmap
m_imgThumb.loadFile(strPath);
// Load a bitmap for active state.
if( L"" != strActivePath )
{
m_imgActive.loadFile(strActivePath);
m_bThumbActive = TRUE;
}
else
m_bThumbActive = FALSE;
// Get size of the bitmap
m_nThumbWidth = m_imgThumb.Width();
m_nThumbHeight = m_imgThumb.Hight();
m_bThumb = TRUE;
return TRUE;
}
// OnLButtonDown
//
// Dragging is started
//
void CImgSliderDEx::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 CImgSliderDEx::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 CImgSliderDEx::OnLButtonUp(UINT nFlags, CPoint point)
{
if( !m_bEnable )
return;
ReleaseCapture();
m_bLButtonDown = FALSE;
Invalidate();
::PostMessage(
GetParent()->GetSafeHwnd(), WM_BITMAPSLIDER_MOVED,
GetDlgCtrlID(), point.x );//m_nPos
CStatic::OnLButtonUp(nFlags, point);
}
// Calculate point of thumb from position value
//
int CImgSliderDEx::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 CImgSliderDEx::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 )
);
}
}
void DrawImg(
CDC* pDC, int xStart, int yStart, int wWidth, int wHeight,
COM_IMAGE* pImg, int xSource, int ySource)
{
pImg->drawImage(pDC,CRect(xStart,yStart,xStart+wWidth,yStart+wHeight),
CRect(xSource,ySource,xSource+wWidth,ySource+wHeight));
}
// To get keyboard input
//
UINT CImgSliderDEx::OnGetDlgCode()
{
if( GetKeyState(VK_TAB) >= 0 )
{
return DLGC_WANTALLKEYS;
}
return CStatic::OnGetDlgCode();
}
// Handling keyboard input
//
void CImgSliderDEx::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 CImgSliderDEx::OnKillFocus(CWnd* pNewWnd)
{
CStatic::OnKillFocus(pNewWnd);
m_bFocus = FALSE;
Invalidate();
}
// This control gains its focus
//
void CImgSliderDEx::OnSetFocus(CWnd* pOldWnd)
{
CStatic::OnSetFocus(pOldWnd);
m_bFocus = TRUE;
Invalidate();
}
// Release resources
//
void CImgSliderDEx::OnDestroy()
{
CStatic::OnDestroy();
m_imgChannel.Release();
m_imgChannelActive.Release();
m_imgThumb.Release();
m_imgActive.Release();
}