📄 peakmeterctrl.cpp
字号:
///////////////////////////////////////////////////////////////////////////////
// File: PeakMeterCtrl.cpp
// Version: 1.2
//
// Author: Ernest Laurentin
// E-mail: elaurentin@sympatico.ca
//
// Implementation of the CPeakMeterCtrl and associated classes.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this c++ class may cause.
//
// Version history
//
// 1.0 - Initial release.
// 1.1 - Impoved Falloff effect to look more like Audio system
// 1.2 - Added 3 ranges of color (low, medium, high)
///////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <mmsystem.h>
#include "MemDC.h"
#include "PeakMeterCtrl.h"
#pragma comment(lib, "winmm.lib")
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
template <class T>
bool InRange(const T val, const T valMin, const T valMax)
{
return ( val >= valMin && val <= valMax );
}
COLORREF LightenColor(const COLORREF crColor, BYTE byIncreaseVal)
{
BYTE byRed = GetRValue(crColor);
BYTE byGreen = GetGValue(crColor);
BYTE byBlue = GetBValue(crColor);
byRed = (byRed + byIncreaseVal) <= 255 ? BYTE(byRed + byIncreaseVal) : 255;;
byGreen = (byGreen + byIncreaseVal) <= 255 ? BYTE(byGreen + byIncreaseVal) : 255;
byBlue = (byBlue + byIncreaseVal) <= 255 ? BYTE(byBlue + byIncreaseVal) : 255;
return RGB(byRed, byGreen, byBlue);
}
COLORREF DarkenColor(const COLORREF crColor, BYTE byReduceVal)
{
BYTE byRed = GetRValue(crColor);
BYTE byGreen = GetGValue(crColor);
BYTE byBlue = GetBValue(crColor);
byRed = byRed >= byReduceVal ? BYTE(byRed - byReduceVal) : 0;
byGreen = byGreen >= byReduceVal ? BYTE(byGreen - byReduceVal) : 0;
byBlue = (byBlue >= byReduceVal) ? BYTE(byBlue - byReduceVal) : 0;
return RGB(byRed, byGreen, byBlue);
}
///////////////////////////////////////////////////////////////////////////////
// PeakMeterData class members
PeakMeterData& PeakMeterData::Copy(const PeakMeterData& pm)
{
nValue = pm.nValue;
nFalloff = pm.nFalloff;
nPeak = pm.nPeak;
return *this;
}
bool PeakMeterData::IsEqual(const PeakMeterData& pm)
{
return (nValue == pm.nValue);
}
bool PeakMeterData::IsGreater(const PeakMeterData& pm)
{
return ( nValue > pm.nValue );
}
bool PeakMeterData::IsLower(const PeakMeterData& pm)
{
return ( nValue < pm.nValue );
}
/////////////////////////////////////////////////////////////////////////////
// CPeakMeterCtrl
CPeakMeterCtrl::CPeakMeterCtrl()
{
TIMECAPS timecaps = {0};
MMRESULT mmresult = timeGetDevCaps(&timecaps, sizeof(timecaps));
mmresult = timeBeginPeriod( timecaps.wPeriodMin );
// Initializes all data
InitData();
}
CPeakMeterCtrl::~CPeakMeterCtrl()
{
TIMECAPS timecaps = {0};
MMRESULT mmresult = timeGetDevCaps(&timecaps, sizeof(timecaps));
mmresult = timeEndPeriod( timecaps.wPeriodMin );
}
BEGIN_MESSAGE_MAP(CPeakMeterCtrl, CWnd)
//{{AFX_MSG_MAP(CPeakMeterCtrl)
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_PAINT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
///////////////////////////////////////////////////////////////////////////////
// Create
BOOL CPeakMeterCtrl::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
// TODO: Add your specialized code here and/or call the base class
dwStyle |= WS_CHILD;
return CWnd::Create(NULL, NULL, dwStyle, rect, pParentWnd, nID, pContext);
}
///////////////////////////////////////////////////////////////////////////////
// PreSubclassWindow
void CPeakMeterCtrl::PreSubclassWindow()
{
ResetControl();
CWnd::PreSubclassWindow();
}
///////////////////////////////////////////////////////////////////////////////
// InitData
void CPeakMeterCtrl::InitData()
{
const COLORREF colLime = RGB( 0,255, 0);
const COLORREF colRed = RGB(255, 0, 0);
const COLORREF colYellow = RGB(255, 255, 0);
m_bShowGrid = false;
m_bShowFalloff = true;
m_uTimerID = 0; // no timer
m_nDelay = DELAY_10MS;
m_nMinValue = 60; // Min Range 0-60
m_nMedValue = 80; // Med Range 60-80
m_nMaxValue = 100; // Max Range 80-100
m_nNumBands = BAND_DEFAULT;
m_nLedBands = LEDS_DEFAULT;
m_clrBackground = GetSysColor(COLOR_3DFACE);
m_clrNormal = colLime;
m_clrMedium = colYellow;
m_clrHigh = colRed;
m_nSpeed = DEFAULT_SPEED;
// clear vector data
m_MeterData.clear();
}
///////////////////////////////////////////////////////////////////////////////
// ResetControl
void CPeakMeterCtrl::ResetControl()
{
// Initialize vector
m_MeterData.resize( m_nNumBands);
// default data
PeakMeterData pm;
pm.nValue = m_nMaxValue;
pm.nFalloff = m_nMaxValue;
pm.nPeak = m_nSpeed;
for(int i=0; i < m_MeterData.size(); i++)
{
m_MeterData.at(i) = pm;
}
}
///////////////////////////////////////////////////////////////////////////////
// SetBackgroundColor
// DESCRIPTION: Set background color for this control
void CPeakMeterCtrl::SetBackgroundColor(COLORREF colorBgnd)
{
m_clrBackground = colorBgnd;
}
///////////////////////////////////////////////////////////////////////////////
// SetBandsColor
// DESCRIPTION: Set bands color for this control
void CPeakMeterCtrl::SetBandsColor(COLORREF colorNormal, COLORREF colorMedium, COLORREF colorHigh)
{
m_clrNormal = colorNormal;
m_clrMedium = colorMedium;
m_clrHigh = colorHigh;
}
///////////////////////////////////////////////////////////////////////////////
// SetMeterBands
// DESCRIPTION: Set number of Vertical or Horizontal bands to display
// NOTES: Obtain smooth effect by setting nHorz or nVert to "1", these
// cannot be 0
void CPeakMeterCtrl::SetMeterBands(int nNumBands, int nLedBands)
{
ASSERT( nNumBands>0 && nLedBands>0 );
if (nNumBands == 0 || nLedBands == 0)
return;
m_nNumBands = nNumBands;
m_nLedBands = nLedBands;
// Reset vector
ResetControl();
}
///////////////////////////////////////////////////////////////////////////////
// SetRangeValue
// Min: [0 - nMin[, Med: [nMin - nMed[, Max: [nMed - nMax]
void CPeakMeterCtrl::SetRangeValue(int nMin, int nMed, int nMax)
{
ASSERT( nMax > nMed && nMed > nMin && nMin > 0);
m_nMinValue = nMin;
m_nMedValue = nMed;
m_nMaxValue = nMax;
}
///////////////////////////////////////////////////////////////////////////////
// GetRangeValue
// DESCRIPTION: Get Range value of this control
void CPeakMeterCtrl::GetRangeValue(int* lpiMin, int* lpiMed, int* lpiMax) const
{
if (NULL != lpiMin)
*lpiMin = m_nMinValue;
if (NULL != lpiMed)
*lpiMed = m_nMedValue;
if (NULL != lpiMax)
*lpiMax = m_nMaxValue;
}
///////////////////////////////////////////////////////////////////////////////
// SetFalloffDelay
// DESCRIPTION: Set Peak value speed before falling off
void CPeakMeterCtrl::SetFalloffDelay(int nSpeed)
{
m_nSpeed = nSpeed;
}
///////////////////////////////////////////////////////////////////////////////
// SetFalloffEffect
// DESCRIPTION: Set falloff effect flag
void CPeakMeterCtrl::SetFalloffEffect(bool bFalloffEffect)
{
if (m_bShowFalloff != bFalloffEffect)
{
m_bShowFalloff = bFalloffEffect;
Refresh();
}
}
///////////////////////////////////////////////////////////////////////////////
// GetFalloffEffect
// DESCRIPTION: Read falloff effect flag
bool CPeakMeterCtrl::GetFalloffEffect() const
{
return m_bShowFalloff;
}
///////////////////////////////////////////////////////////////////////////////
// ShowGrid
// DESCRIPTION: Request to have gridlines visible or not
void CPeakMeterCtrl::ShowGrid(bool bShowGrid)
{
if (m_bShowGrid != bShowGrid)
{
m_bShowGrid = bShowGrid;
Refresh();
}
}
///////////////////////////////////////////////////////////////////////////////
// IsGridVisible
// DESCRIPTION: Returns if gridlines are visible
bool CPeakMeterCtrl::IsGridVisible() const
{
return m_bShowGrid;
}
///////////////////////////////////////////////////////////////////////////////
// SetData
// DESCRIPTION: Change data value. Use this function to change only
// a set of values. All bands can be changed or only 1 band.
// Depending on the application.
bool CPeakMeterCtrl::SetData(const int ArrayValue[], int nOffset, int nSize)
{
ASSERT( nOffset >= 0 && ArrayValue != NULL);
if (nOffset < 0 || ArrayValue == NULL)
return false;
bool bIsRunning = IsStarted();
// Stop timer if Animation is active
if ( bIsRunning )
Stop();
int nMaxSize = nOffset + nSize;
for(int i=nOffset; i < nMaxSize; i++)
{
if (i < m_MeterData.size())
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -