www.pudn.com > Éù²¨ÆµÂÊÏÔʾ .zip > VuMeterCtrl.cpp


/********************************************************************/ 
/*																	*/ 
/*  VuMeterCtrl.cpp													*/ 
/*																	*/ 
/*  Implementation of the CVuMeterCtrl.								*/ 
/*																	*/ 
/*  Programmed by Pablo van der Meer								*/ 
/*  Copyright Pablo Software Solutions 2003							*/ 
/*	http://www.pablovandermeer.nl									*/ 
/*																	*/ 
/*  Last updated: 1 January 2003									*/ 
/*																	*/ 
/********************************************************************/ 
 
 
#include "stdafx.h" 
#include "VuMeterCtrl.h" 
#include  
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
 
CVuMeterCtrl::CVuMeterCtrl() 
{ 
	m_pOldBitmap = NULL; 
 
    m_nCurVal = 0; 
    m_nMinVal = 0; 
    m_nMaxVal = 100; 
 
	m_clrStart = RGB(0,255,0); 
	m_clrEnd = RGB(255,0,0); 
 
	m_bVertical = FALSE; 
	m_bSmooth = FALSE; 
} 
 
CVuMeterCtrl::~CVuMeterCtrl() 
{ 
	if (m_pOldBitmap != NULL) 
		m_MainDC.SelectObject(m_pOldBitmap);   
} 
 
 
BEGIN_MESSAGE_MAP(CVuMeterCtrl, CStatic) 
	//{{AFX_MSG_MAP(CVuMeterCtrl) 
	ON_WM_PAINT() 
	ON_WM_SIZE() 
	ON_WM_TIMER() 
	ON_WM_DESTROY() 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnPaint											*/ 
/* Description   : Called when the application makes a request to	*/ 
/*				   repaint a portion of the window.					*/ 
/*																	*/ 
/********************************************************************/ 
void CVuMeterCtrl::OnPaint()  
{ 
	CPaintDC dc(this); // device context for painting 
	 
	CRect rect; 
	GetClientRect(&rect); 
 
	CDC memDC; 
	CBitmap memBitmap; 
	CBitmap* oldBitmap; 
 
	// to avoid flicker, establish a memory dc, draw to it and then BitBlt it to the client 
	memDC.CreateCompatibleDC(&dc); 
	memBitmap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height()); 
	oldBitmap = (CBitmap *)memDC.SelectObject(&memBitmap); 
 
	if (memDC.GetSafeHdc() != NULL) 
	{ 
		// first drop the bitmap on the memory dc 
		memDC.BitBlt(0, 0, rect.Width(), rect.Height(), &m_MainDC, 0, 0, SRCCOPY); 
		// finally send the result to the display 
		dc.BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY); 
	} 
	memDC.SelectObject(oldBitmap); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnSize											*/ 
/* Description   : The framework calls this member function after	*/ 
/*				   the window’s size has changed.					*/ 
/*																	*/ 
/********************************************************************/ 
void CVuMeterCtrl::OnSize(UINT nType, int cx, int cy)  
{ 
	// OnSize automatically gets called during the setup of the control 
	CStatic::OnSize(nType, cx, cy); 
	 
	CRect rect; 
	GetClientRect(&rect); 
 
	// destroy and recreate the main bitmap 
	CClientDC dc(this); 
 
	if (m_pOldBitmap && m_MainBitmap.GetSafeHandle() && m_MainDC.GetSafeHdc()) 
	{ 
		m_MainDC.SelectObject(m_pOldBitmap); 
		m_MainBitmap.DeleteObject(); 
		m_MainBitmap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height()); 
		m_pOldBitmap = m_MainDC.SelectObject(&m_MainBitmap); 
	}	 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : DrawCtrl											*/ 
/* Description   : Render the vumeter to a bitmap.					*/ 
/*																	*/ 
/********************************************************************/ 
void CVuMeterCtrl::DrawCtrl() 
{ 
	CRect rect; 
	GetClientRect(&rect); 
 
	// in case we haven't established the memory dc's 
	CClientDC dc(this); 
 
	// if we don't have one yet, set up a memory dc for the control  
	if (m_MainDC.GetSafeHdc() == NULL) 
	{ 
		m_MainDC.CreateCompatibleDC(&dc); 
		m_MainBitmap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height()); 
		m_pOldBitmap = m_MainDC.SelectObject(&m_MainBitmap); 
	} 
 
	// background  
	COLORREF clrBackground = RGB(0,0,0); 
	 
	double nScale; 
	 
	if (m_bVertical)  
		nScale = (double)rect.Height()/(double)255; 
	else 
		nScale = (double)rect.Width()/(double)255; 
 
	m_MainDC.Draw3dRect(rect, GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_3DHILIGHT)); 
    rect.InflateRect(-2, -2); 
 
	m_MainDC.FillSolidRect(rect, clrBackground); 
 
    int nRightBar, nLedWidth; 
 
    // compute extent of progress bar  
    if (m_bVertical)  
	{ 
		nRightBar  = rect.bottom - MulDiv(m_nCurVal - m_nMinVal, rect.Height(), m_nMaxVal - m_nMinVal); 
        nLedWidth = MulDiv(rect.Width(), 2, 3); 
    }  
	else  
	{ 
        nRightBar = rect.left + MulDiv(m_nCurVal - m_nMinVal, rect.Width(), m_nMaxVal - m_nMinVal); 
        nLedWidth = MulDiv(rect.Height(), 2, 3); 
    } 
 
	// stay between the lines... 
	CRgn rgn; 
	rgn.CreateRectRgn(rect.left, rect.top, rect.right, rect.bottom); 
	m_MainDC.SelectClipRgn(&rgn); 
 
    // now draw the bar  
    if (m_bSmooth) 
    { 
        if (m_bVertical) 
        { 
			// create gradient  
			for(int i=rect.bottom-1; i > nRightBar-1; i-=1) 
			{ 
				int nStep = (int)((double)i/nScale); 
 
				// set current color 
				COLORREF clr = RGB((GetRValue(m_clrStart)-GetRValue(m_clrEnd))* 
									((float)nStep)/255.0f+GetRValue(m_clrEnd), 
									(GetGValue(m_clrStart)-GetGValue(m_clrEnd))* 
									((float)nStep)/255.0f+GetGValue(m_clrEnd), 
									(GetBValue(m_clrStart)-GetBValue(m_clrEnd))* 
									((float)nStep)/255.0f+GetBValue(m_clrEnd)); 
 
				m_MainDC.FillSolidRect(rect.left, i, rect.Width(), 1, clr); 
			} 
        } 
        else 
        { 
			// create gradient  
			for(int i=rect.left; i < nRightBar; i+=1) 
			{ 
				int nStep = (int)((double)i/nScale); 
 
				// set current color 
				COLORREF clr = RGB((GetRValue(m_clrEnd)-GetRValue(m_clrStart))* 
									((float)nStep)/255.0f+GetRValue(m_clrStart), 
									(GetGValue(m_clrEnd)-GetGValue(m_clrStart))* 
									((float)nStep)/255.0f+GetGValue(m_clrStart), 
									(GetBValue(m_clrEnd)-GetBValue(m_clrStart))* 
									((float)nStep)/255.0f+GetBValue(m_clrStart)); 
 
				m_MainDC.FillSolidRect(i, rect.top, 1, rect.Height(), clr); 
			} 
        } 
    }  
	else  
	{ 
        if (m_bVertical)  
		{ 
			// create gradient  
			for(int i=rect.bottom+1; i > nRightBar; i-=nLedWidth) 
			{ 
				int nStep = (int)((double)i/nScale); 
 
				// set current color 
				COLORREF clr = RGB((GetRValue(m_clrStart)-GetRValue(m_clrEnd))* 
									((float)nStep)/255.0f+GetRValue(m_clrEnd), 
									(GetGValue(m_clrStart)-GetGValue(m_clrEnd))* 
									((float)nStep)/255.0f+GetGValue(m_clrEnd), 
									(GetBValue(m_clrStart)-GetBValue(m_clrEnd))* 
									((float)nStep)/255.0f+GetBValue(m_clrEnd)); 
 
				m_MainDC.FillSolidRect(rect.left, i, rect.Width(), nLedWidth-2, clr); 
			} 
        }  
		else  
		{ 
			// create gradient  
			for(int i=rect.left; i < nRightBar; i+=nLedWidth) 
			{ 
				int nStep = (int)((double)i/nScale); 
 
				// set current color 
				COLORREF clr = RGB((GetRValue(m_clrEnd)-GetRValue(m_clrStart))* 
									((float)nStep)/255.0f+GetRValue(m_clrStart), 
									(GetGValue(m_clrEnd)-GetGValue(m_clrStart))* 
									((float)nStep)/255.0f+GetGValue(m_clrStart), 
									(GetBValue(m_clrEnd)-GetBValue(m_clrStart))* 
									((float)nStep)/255.0f+GetBValue(m_clrStart)); 
 
				m_MainDC.FillSolidRect(i, rect.top, nLedWidth-2, rect.Height()-1, clr); 
			} 
        } 
    } 
	rgn.DeleteObject(); 
 
	// finally, force redraw 
	Invalidate(); 
}  
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : PreSubclassWindow								*/ 
/* Description   : Initialize some stuff							*/ 
/*																	*/ 
/********************************************************************/ 
void CVuMeterCtrl::PreSubclassWindow()  
{ 
	CStatic::PreSubclassWindow(); 
 
	DrawCtrl(); 
 
//	SetTimer(1, 100, NULL); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnDestroy										*/ 
/* Description   : Cleanup stuff									*/ 
/*																	*/ 
/********************************************************************/ 
void CVuMeterCtrl::OnDestroy()  
{ 
	KillTimer(1); 
	CStatic::OnDestroy(); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : SetRange											*/ 
/* Description   : Set the upper and lower limits of the control’s	*/ 
/*				   range. 											*/ 
/*																	*/ 
/********************************************************************/ 
void CVuMeterCtrl::SetRange(int nMin, int nMax) 
{ 
	m_nMinVal = nMin; 
	m_nMaxVal = nMax; 
	DrawCtrl(); 
}	 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : SetValue											*/ 
/* Description   : Set the control’s current value					*/ 
/*																	*/ 
/********************************************************************/ 
void CVuMeterCtrl::SetValue(int nValue) 
{ 
//	if (nValue > m_nCurVal)  
	{ 
		m_nCurVal = nValue; 
	}  
 
	DrawCtrl(); 
 
	if (nValue) 
		SetTimer(1, 100, NULL); 
	else 
		KillTimer(1); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : SetColors										*/ 
/* Description   : Set the control’s start and end colors			*/ 
/*																	*/ 
/********************************************************************/ 
void CVuMeterCtrl::SetColors(COLORREF clrStart, COLORREF clrEnd) 
{ 
	m_clrStart = clrStart; 
	m_clrEnd = clrEnd; 
	DrawCtrl(); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : SetVertical										*/ 
/* Description   : Displays control vertically (instead of			*/ 
/*				   horizontally).									*/ 
/*																	*/ 
/********************************************************************/ 
void CVuMeterCtrl::SetVertical(BOOL bVertical) 
{ 
	m_bVertical = bVertical; 
	DrawCtrl(); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : SetSmooth										*/ 
/* Description   : Fills the progress control smoothly, rather than */ 
/*				   using a segmented fill.							*/ 
/*																	*/ 
/********************************************************************/ 
void CVuMeterCtrl::SetSmooth(BOOL bSmooth) 
{ 
	m_bSmooth = bSmooth; 
	DrawCtrl(); 
} 
 
 
/********************************************************************/ 
/*																	*/ 
/* Function name : OnTimer											*/ 
/* Description   : Handle timer event								*/ 
/*																	*/ 
/********************************************************************/ 
void CVuMeterCtrl::OnTimer(UINT nIDEvent)  
{ 
	if (nIDEvent == 1) 
	{ 
		// Update the peak value 
		int nDiff = m_nCurVal / 10; 
		if (nDiff == 0)  
		{ 
			nDiff = 1; 
		} 
		m_nCurVal -= nDiff; 
		if (m_nCurVal < 0)  
		{ 
			m_nCurVal = 0; 
			KillTimer(1); 
		} 
		DrawCtrl(); 
    }	 
	CStatic::OnTimer(nIDEvent); 
}