www.pudn.com > VC写的MP3播放器源代码.zip > BytesTracer.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(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(rSgE) 
							gS-=step; 
						else if(gSbE) 
							bS-=step; 
						else if(bSSetBkColor(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); 
}