⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bytestracer.cpp

📁 完整的MP3播放器源码
💻 CPP
字号:
/////////////////////////////////////////////////////////////////////////////
// BytesTracer.cpp : implementation file
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "BytesTracer.h"
#include "math.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
BOOL	CBytesTracer::CreateTracer();
int		CBytesTracer::PaintProc(LPVOID pvData);
LPCSTR	CBytesTracer::m_pWndName PURE;
/////////////////////////////////////////////////////////////////////////////
// CBytesTracer
CBytesTracer::CBytesTracer():m_dropStep(4),m_backColor(RGB(0,0,0)),
										m_overColor(RGB(255,255,0)), // pick color
										m_endColor(RGB(0,255,255)),
										m_startColor(RGB(255,255,0)),
										m_mLeduri(30)
{
}
/////////////////////////////////////////////////////////////////////////////
//
CBytesTracer::~CBytesTracer()
{
}

/////////////////////////////////////////////////////////////////////////////
//  The vu don't uses a buffer. It use on value. And the reast is done
//  To adjust it for your app tune it from m_dropStep () and Sleep()
//	Set from time to time from the music sample data the vumeter value
//  
void CBytesTracer::SetPick(int value)
{
	EnterCriticalSection(&ms_cs);
	m_pick = (double)value * m_scaleVert;
	LeaveCriticalSection(&ms_cs);
}

/////////////////////////////////////////////////////////////////////////////
//
BEGIN_MESSAGE_MAP(CBytesTracer, CWnd)
	//{{AFX_MSG_MAP(CBytesTracer)
	ON_WM_PAINT()
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_PAINT()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CBytesTracer message handlers
// Hell know how this work, but works, If you get out this  BeginPaint();
// the thread does not paint anymore in the window's DC
void CBytesTracer::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	RECT rt;
	GetClientRect(&rt);    
	CRgn	cr;
	cr.CreateRectRgn(0,0,rt.right,rt.bottom);
	dc.SetBkColor(m_backColor);
	dc.SelectClipRgn(&cr);
	dc.ExtTextOut(0,0,ETO_OPAQUE,&rt,"",0);
}


/////////////////////////////////////////////////////////////////////////////
// registers the new class, callonly one time
BOOL CBytesTracer::CreateTracer()
{
	m_pWndName = AfxRegisterWndClass(CS_OWNDC|CS_HREDRAW|CS_VREDRAW,0,
									(HBRUSH)GetStockObject(BLACK_BRUSH));
	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// pPlaceHolder is the place sholder ID
// creates the window, hides the parent, calculates the scalation factors
BOOL CBytesTracer::CreatWndw(UINT pPlaceHolder, CWnd* pParent)
{
	RECT rt; 
	CWnd* pWnd = pParent->GetDlgItem(pPlaceHolder);
	pWnd->GetWindowRect(&rt);

	pParent->ScreenToClient(&rt);
	
	CreateEx( /*WS_EX_CLIENTEDGE*/0, m_pWndName , "", 
						WS_CHILD|WS_VISIBLE,rt.left,rt.top,
						rt.right-rt.left,rt.bottom-rt.top,
						pParent->m_hWnd,(HMENU)10000); 
	pWnd->ShowWindow(SW_HIDE);

	if((rt.right-rt.left) > (rt.bottom-rt.top))
		m_position = HORIZONTAL;
	else
		m_position = VERTICAL;
	SetLimits(0,100);
	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
//
//
int CBytesTracer::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	
	if (CWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	InitializeCriticalSection(&ms_cs);

	m_cbr.CreateSolidBrush(m_backColor);

	// background color. The m_XXXXXColor should be set before calling the createwndw()

	CDC* pdc = GetDC();
	m_pcbr = (CBrush*)pdc->SelectObject(&m_cbr);

	// not recomanded to make a copy and to pass it to a thread
	// but the crap works, and does not leak GDI's
	m_hdc = pdc->m_hDC;

	// if you use it for 8 bits  set the limit to 128
	// if you use it for 16 bits set the limit to 32768

	// this is the default for this demo or if the SetLimits() is not called
	SetLimits(0,100);
	
	
	RECT rt; GetClientRect(&rt);
	m_clrscale = (double)rt.right/(double)255;

	// painting thread
	DWORD dw = 0;
	m_noClose = TRUE;
	m_hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)PaintProc,this,0,&dw); 
    SetThreadPriority(m_hThread,THREAD_PRIORITY_LOWEST);

	return 0;
}


/////////////////////////////////////////////////////////////////////////////
//
void CBytesTracer::OnDestroy() 
{
	// redo the brush in the dc
	CDC* pdc = GetDC();
	(CBrush*)pdc->SelectObject(m_pcbr);
	m_cbr.DeleteObject();

	// !!! should or not I don't know, is a copy of GetDC()
	// I don't have time to study, the true is that it dont leaks GDI's
	
	ReleaseDC(pdc);
	::ReleaseDC(m_hWnd,m_hdc);
	m_noClose  = FALSE;
	WaitForSingleObject(m_hThread,INFINITE);
    
	DeleteCriticalSection(&ms_cs);
	
	CWnd::OnDestroy();
}


/////////////////////////////////////////////////////////////////////////////
//
void CBytesTracer::SetLimits(int min, int max)
{
	RECT	rt;
	GetClientRect(&rt);
	if(m_position == VERTICAL)
		m_scaleVert = (double)rt.bottom/(double)(max-min);
	else
		m_scaleVert = (double)rt.right/(double)(max-min);

}


/////////////////////////////////////////////////////////////////////////////
//
int	 CBytesTracer::PaintProc(LPVOID pvData)
{
	CBytesTracer* pBt = reinterpret_cast<CBytesTracer*>(pvData);
	CDC* pDC = CDC::FromHandle(pBt->m_hdc);
	pBt->PaintThread(pDC);
	pBt->ReleaseDC(pDC);
	return 1;
}
	
/////////////////////////////////////////////////////////////////////////////
//
void CBytesTracer::PaintThread(CDC* pDC)
{
	int		i;
	int		nLevel = 0;
	RECT	rt,rc;
	GetClientRect(&rt);
	rt.bottom--; // let a line in this demo
	CBrush	cb(m_backColor);
    CRgn	cr;
	int     ledWide ;
	if(m_position == VERTICAL)
		ledWide = rt.bottom / m_mLeduri;
	else
		ledWide = rt.right / m_mLeduri;
	ASSERT(ledWide>1);
    
    m_dropStep = min(2,ledWide / 3);
	BOOL bOne = FALSE;

	do
	{
		//read the level
        EnterCriticalSection(&ms_cs);
		if(m_pick)
		{
			nLevel = max(nLevel,(int)m_pick);
			m_pick = 0.0f;
			bOne = TRUE;
		}
		LeaveCriticalSection(&ms_cs);
			
		if(bOne)
		{
			// paint the pick one time at it's maximum value
       		CopyRect(&rc,&rt);
			int oc = pDC->SetBkColor(m_backColor);
			for( i=0; i < nLevel; i+=ledWide)
			{
				if(m_position == VERTICAL)
				{
					// do-it your self
				}
				else
				{
					cr.CreateRectRgn(i,0,i+ledWide-1,rt.bottom-1);
					pDC->SelectClipRgn(&cr);

					if(i >= rt.right - (rt.right/10))
						pDC->SetBkColor(m_overColor);
					else
					{
						// create degradee colors
						int step = (int)((double)i/m_clrscale);

						double	bS = (m_startColor & 0x00FF0000)>>16;
						double	gS = (m_startColor & 0x0000FF00)>>8;
						double	rS = m_startColor & 0xFF;

						double	bE = (m_endColor & 0x00FF0000)>>16;
						double	gE = (m_endColor & 0x0000FF00)>>8;
						double	rE = (m_endColor & 0xFF);

						// just a dump algorithm
						if(rS>rE)
							rS-=step;
						else if(rS<rE)
							rS+=step;

						if(gS>gE)
							gS-=step;
						else if(gS<gE)
							gS-=step;

						if(bS>bE)
							bS-=step;
						else if(bS<bE)
							bS +=step;
						
						
						pDC->SetBkColor(RGB(rS,gS,bS));//RGB(255,i/m_clrscale,i/m_clrscale));
					}
					rc.right = nLevel;
					pDC->ExtTextOut(0,0,ETO_OPAQUE,&rc,"",0);

					// to get it fast create the regions out of loop
					cr.DeleteObject();
				}

			}
			// restore old color
            pDC->SetBkColor(oc);
			bOne = FALSE;
            
		}
        else if(nLevel<=5)
        {
			// when does not 'meters', 
			// Enter/ExitCriticalSection() will loop just themselfs
			// and eata almost the entire uP time. This sleep
			// keep it cool at 3%(p166) and 0.3% PII-400 (22 of them)
			//
            Sleep(20);
        }
		
		if(nLevel>=0)
		{
			// decrease smoothly 
			CopyRect(&rc,&rt);
			if(m_position == VERTICAL)
			{
				// do it 
			}
			else
			{
				rc.left = nLevel;
				cr.CreateRectRgn(nLevel,0,rt.right,rt.bottom);
				pDC->SetBkColor(m_backColor);
				pDC->SelectClipRgn(&cr);
				pDC->ExtTextOut(0,0,ETO_OPAQUE,&rc,"",0);
				cr.DeleteObject();
			}
			// is ok this sleep. results a fast paint
			// and a low uP usage 0.3% P2-400 and 3% P166. Look at this sample
			// that has 9 vumeters and on p166 the uP usage is 2%. and on P2 400
			// .3% (22 of them)
			Sleep(10);
		}
		else
		{
			// draw code here to delete the led's statting positions
			// when there is no signal
			nLevel = 0;
		}
		nLevel -= m_dropStep;
	
	}while(m_noClose);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -