📄 peakmeterctrl.cpp
字号:
{
PeakMeterData pm = m_MeterData.at( i );
pm.nValue = ArrayValue[i];
if (pm.nFalloff < pm.nValue)
{
pm.nFalloff = pm.nValue;
pm.nPeak = m_nSpeed;
}
m_MeterData.at(i) = pm;
}
}
// Auto-restart
if ( bIsRunning )
return Start( m_nDelay );
Refresh();
return true;
}
///////////////////////////////////////////////////////////////////////////////
// Refresh
// DESCRIPTION: Invalidate the control
void CPeakMeterCtrl::Refresh()
{
if (::IsWindow( GetSafeHwnd() ))
Invalidate();
}
///////////////////////////////////////////////////////////////////////////////
// IsStarted
// DESCRIPTION: Check if animation is active
bool CPeakMeterCtrl::IsStarted() const
{
return (m_uTimerID > 0);
}
///////////////////////////////////////////////////////////////////////////////
// Start
// DESCRIPTION: Start the timer and animation effect
bool CPeakMeterCtrl::Start(UINT uDelay)
{
if ( !IsStarted() )
{
MMRESULT mmresult;
mmresult = timeSetEvent(uDelay, 0, PeakTimerProc, (DWORD)this, TIME_PERIODIC);
m_uTimerID = (UINT) mmresult;
m_nDelay = uDelay;
}
return (m_uTimerID != 0);
}
///////////////////////////////////////////////////////////////////////////////
// Stop
// DESCRIPTION: Stop the timer and animation effect
bool CPeakMeterCtrl::Stop()
{
if ( IsStarted() )
{
timeKillEvent( m_uTimerID );
m_uTimerID = 0;
return true;
}
return false;
}
///////////////////////////////////////////////////////////////////////////////
// DoTimerProcessing
// DESCRIPTION: Peak Meter animation - virtual
void CPeakMeterCtrl::DoTimerProcessing(UINT uID)
{
Refresh();
int nDecValue = m_nMaxValue / m_nLedBands;
bool bNoChange = true;
for(int i=0; i < m_MeterData.size(); i++)
{
PeakMeterData pm = m_MeterData.at(i);
if (pm.nValue > 0)
{
pm.nValue -= ( m_nLedBands>1 ? nDecValue : m_nMaxValue*BAND_PERCENT/100);
if (pm.nValue < 0)
pm.nValue = 0;
bNoChange = false;
}
if (pm.nPeak > 0)
{
pm.nPeak -= 1;
bNoChange = false;
}
if (pm.nPeak == 0 && pm.nFalloff > 0)
{
pm.nFalloff -= (m_nLedBands>1 ? nDecValue>>1 : 5);
if (pm.nFalloff < 0)
pm.nFalloff = 0;
bNoChange = false;
}
// re-assign PeakMeterData
m_MeterData.at(i) = pm;
}
if (bNoChange) // Stop timer if no more data but do not reset ID
{
timeKillEvent( m_uTimerID );
}
}
///////////////////////////////////////////////////////////////////////////////
// CPeakMeterCtrl message handlers
///////////////////////////////////////////////////////////////////////////////
// OnCreate
int CPeakMeterCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
//InitControl();
return 0;
}
///////////////////////////////////////////////////////////////////////////////
// OnDestroy
void CPeakMeterCtrl::OnDestroy()
{
Stop();
// clear vector data
m_MeterData.clear();
CWnd::OnDestroy();
}
///////////////////////////////////////////////////////////////////////////////
// OnPaint
// DESCRIPTION: Paint this control
void CPeakMeterCtrl::OnPaint()
{
CPaintDC dc(this); // device context for painting
CRect rc;
GetWindowRect( rc );
rc.OffsetRect(-rc.left, -rc.top);
CMemDC memdc(&dc, &rc);
memdc.SetBkMode(TRANSPARENT);
memdc.FillSolidRect( rc, m_clrBackground);
CPen pen;
//pen.CreatePen(PS_SOLID, 1, RGB(255,0,0));
pen.CreatePen(PS_SOLID, 1, DarkenColor(m_clrBackground, GRID_INCREASEBY));
CPen* pOldPen = (CPen*) memdc.SelectObject( & pen );
if (GetStyle() & PMS_VERTICAL)
DrawVertBand(&memdc, rc);
else
DrawHorzBand(&memdc, rc);
memdc.SelectObject( pOldPen );
// Do not call CWnd::OnPaint() for painting messages
}
///////////////////////////////////////////////////////////////////////////////
// DrawVertBand
// DESCRIPTION: Draw Vertical bands - No falloff effect for vertical bands
void CPeakMeterCtrl::DrawVertBand(CDC* pDC, CRect& rcClient)
{
int nHorzBands = (m_nLedBands>1 ? m_nLedBands : m_nMaxValue*BAND_PERCENT/100);
int nMinHorzLimit = m_nMinValue*nHorzBands/m_nMaxValue;
int nMedHorzLimit = m_nMedValue*nHorzBands/m_nMaxValue;
int nMaxHorzLimit = nHorzBands;
CSize size;
size.cx = rcClient.Width()/nHorzBands;
size.cy = rcClient.Height()/m_nNumBands;
CRect rcBand( rcClient.TopLeft(), size);
// Draw band from top
rcBand.OffsetRect(0, rcClient.Height()-size.cy*m_nNumBands);
int xDecal = (m_nLedBands>1 ? 1 : 0);
int yDecal = (m_nNumBands>1 ? 1 : 0);
for(int nVert=0; nVert < m_nNumBands; nVert++)
{
int nValue = m_MeterData.at(nVert).nValue;
int nHorzLimit = nValue*nHorzBands/m_nMaxValue;
for(int nHorz=0; nHorz < nHorzBands; nHorz++)
{
rcBand.DeflateRect(xDecal, yDecal, 0, yDecal);
// Find color based on range value
COLORREF colorRect = m_clrBackground;
if (true == m_bShowGrid)
colorRect = DarkenColor(m_clrBackground, GRID_INCREASEBY);
if ( m_bShowGrid && (nHorz == nMinHorzLimit || nHorz == (nHorzBands-1)))
{
POINT points[2] = { 0 };
points[0].x = rcBand.TopLeft().x + (rcBand.Width()>>1);
points[0].y = rcBand.TopLeft().y - yDecal;
points[1].x = points[0].x;
points[1].y = rcBand.BottomRight().y + yDecal;
pDC->Polyline( points, 2);
}
if ( nHorz < nHorzLimit)
{
if ( InRange<int>(nHorz, 0, nMinHorzLimit-1) )
colorRect = m_clrNormal;
else if ( InRange<int>(nHorz, nMinHorzLimit, nMedHorzLimit-1) )
colorRect = m_clrMedium;
else if ( InRange<int>(nHorz, nMedHorzLimit, nMaxHorzLimit) )
colorRect = m_clrHigh;
}
pDC->FillSolidRect( rcBand, colorRect);
rcBand.InflateRect(xDecal, yDecal, 0, yDecal);
rcBand.OffsetRect(size.cx, 0);
}
// Move to Next Vertical band
rcBand.OffsetRect(-size.cx*nHorzBands, size.cy);
}
}
///////////////////////////////////////////////////////////////////////////////
// DrawHorzBand
// DESCRIPTION: Draw Horizontal bands - with Falloff effect
void CPeakMeterCtrl::DrawHorzBand(CDC* pDC, CRect& rcClient)
{
int nVertBands = (m_nLedBands>1 ? m_nLedBands : m_nMaxValue*BAND_PERCENT/100);
int nMinVertLimit = m_nMinValue*nVertBands/m_nMaxValue;
int nMedVertLimit = m_nMedValue*nVertBands/m_nMaxValue;
int nMaxVertLimit = nVertBands;
CSize size;
size.cx = rcClient.Width()/m_nNumBands;
size.cy = rcClient.Height()/nVertBands;
CRect rcBand( rcClient.TopLeft(), size);
// Draw band from bottom
rcBand.OffsetRect(0, rcClient.bottom-size.cy);
int xDecal = (m_nNumBands>1 ? 1 : 0);
int yDecal = (m_nLedBands>1 ? 1 : 0);
for(int nHorz=0; nHorz < m_nNumBands; nHorz++)
{
int nValue = m_MeterData.at(nHorz).nValue;
int nVertLimit = nValue*nVertBands/m_nMaxValue;
CRect rcPrev = rcBand;
for(int nVert=0; nVert < nVertBands; nVert++)
{
rcBand.DeflateRect(xDecal, yDecal, xDecal, 0);
// Find color based on range value
COLORREF colorRect = m_clrBackground;
if ( true == m_bShowGrid)
colorRect = DarkenColor(m_clrBackground, GRID_INCREASEBY);
// Draw grid line (level) bar
if ( m_bShowGrid && (nVert == nMinVertLimit || nVert == (nVertBands-1)))
{
POINT points[2] = { 0 };
points[0].x = rcBand.TopLeft().x - xDecal;
points[0].y = rcBand.TopLeft().y + (rcBand.Height()>>1);
points[1].x = rcBand.BottomRight().x + xDecal;
points[1].y = points[0].y;
pDC->Polyline( points, 2);
}
if ( nVert < nVertLimit)
{
if ( InRange<int>(nVert, 0, nMinVertLimit-1) )
colorRect = m_clrNormal;
else if ( InRange<int>(nVert, nMinVertLimit, nMedVertLimit-1) )
colorRect = m_clrMedium;
else if ( InRange<int>(nVert, nMedVertLimit, nMaxVertLimit) )
colorRect = m_clrHigh;
}
pDC->FillSolidRect( rcBand, colorRect);
rcBand.InflateRect(xDecal, yDecal, xDecal, 0);
rcBand.OffsetRect(0, -size.cy);
}
// Draw falloff effect
if (m_bShowFalloff)
{
CPen pen;
pen.CreatePen(PS_SOLID, 1, DarkenColor(m_clrBackground, FALL_INCREASEBY));
CPen* pOldPen = (CPen*) pDC->SelectObject(& pen );
int nMaxHeight = size.cy*nVertBands;
POINT points[2] = { 0 };
points[0].x = rcPrev.TopLeft().x + xDecal;
points[0].y = rcPrev.BottomRight().y - m_MeterData.at(nHorz).nFalloff*nMaxHeight/m_nMaxValue;
points[1].x = rcPrev.BottomRight().x - xDecal;
points[1].y = points[0].y;
pDC->Polyline( points, 2);
pDC->SelectObject( pOldPen );
}
// Move to Next Horizontal band
rcBand.OffsetRect(size.cx, size.cy*nVertBands);
}
}
///////////////////////////////////////////////////////////////////////////////
// PeakTimerProc
// DESCRIPTION: Multimedia timer procedure - this is called from another thread
void CALLBACK CPeakMeterCtrl::PeakTimerProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
CPeakMeterCtrl* pThis = reinterpret_cast<CPeakMeterCtrl*>( dwUser );
ASSERT( pThis != NULL );
pThis->DoTimerProcessing( uID );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -