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); }