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

📄 wndgraph.cpp

📁 完整的MP3播放器源码
💻 CPP
字号:
//  WndGraph.cpp : implementation file
//
///////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "resource.h"
#include "math.h"
#include "WndGraph.h"



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

LPCSTR   CWndGraph::m_pWndNameG;
BOOL     CWndGraph::RegisterGraphClass();
int      CWndGraph::PainterThread(void* pData);


#define REFRESH 20 // times/sec

int      DelayThread(void* pData)
{

	((CWndGraph*)pData)->ReleasePaint();
	return 1;
}

CRITICAL_SECTION    CWndGraph::m_cs;
    CWndGraph*   pGTracer;


/////////////////////////////////////////////////////////////////////////////
// CWndGraph

CWndGraph::CWndGraph():  m_graphColor(RGB(0,255,0)),
                         m_gridClr(RGB(128,128,0)), m_axisClr(RGB(255,255,255)),
                         m_pCDC(0),m_hthread(0),m_xOrigin(0),m_yOrigin(0),
                         m_bDown(0),m_iHooked(NONE),
                         m_viewscale(100),m_yWndScale(100),m_xWndScale(1),
                         m_xMin(0),m_yMin(0),m_updateTime(200/*msec*/),
						 m_framesPerBuf(5),
						 m_lastLen(0),
                         m_sleep(60),m_yWndEx(65535),m_mode(0),m_stepy(2000)
{
    InitializeCriticalSection(&CWndGraph::m_cs);
        pGTracer = this;
}


BEGIN_MESSAGE_MAP(CWndGraph, CWnd)
	//{{AFX_MSG_MAP(CWndGraph)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_PAINT()
	ON_WM_SETCURSOR()
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_CANCELMODE()
	ON_WM_RBUTTONDOWN()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CWndGraph message handlers
BOOL CWndGraph::CreateWndw(UINT id, CWnd* pParent)
{

	CWnd* pWnd = pParent->GetDlgItem(id);
    RECT rt;
	pWnd->GetWindowRect(&rt);
	pParent->ScreenToClient(&rt);
    
	CreateEx( WS_EX_CLIENTEDGE, m_pWndNameG , "", 
						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);
	
	return TRUE;
}



int CWndGraph::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	
    SetBkColor(RGB(0,0,0));
    CreatePens();
    UseThreads();
    

    RECT rt;GetClientRect(&rt);
	
    m_xMax = rt.right;
    m_yMax = rt.bottom;
    
    CreateBuffers();


    m_yOrigin  = 0;//rt.bottom/2;
    m_grdStepy = 10;
    m_grdStepx = 10;
	return 0;
}

void CWndGraph::OnDestroy() 
{
	
    if(m_hthread)
    {
        CloseThreadsStuff();
    }

    HBRUSH  hbrOld = (HBRUSH)::SetClassLong(m_hWnd,GCL_HBRBACKGROUND,(LONG)NULL_BRUSH);
    ::DeleteObject(hbrOld);
    m_delPen.DeleteObject();
    m_gridPen.DeleteObject();
    m_axisPen.DeleteObject();
    
    m_grapgPen.DeleteObject();

    
    delete[]  m_Buff1; 
    delete[]  m_Buff2;
    delete[] m_grapPtsBackBuff;


    CWnd::OnDestroy();
}

void CWndGraph::OnPaint() 
{
    Ecs();
    {
    
	    CPaintDC dc(this);

        GridIt(&dc);
        /*
		dc.SetMapMode(MM_ANISOTROPIC);    
		dc.SetWindowExt(100, m_yWndEx);
		dc.SetViewportExt(100, -m_yMax);
		dc.SetWindowOrg(0,0);
		dc.SetViewportOrg(0, m_yMax);

        CPen*       pOld  = (CPen*)dc.SelectObject(&m_grapgPen);
        dc.MoveTo(0,32768);
        dc.LineTo(m_xMax,32768);
        dc.SelectObject(pOld);
    */
    }
    Xcs();
 
}

BOOL CWndGraph::CreatePens()
{
    m_axisPen.CreatePen(PS_SOLID,1,m_axisClr);
    m_gridPen.CreatePen(PS_SOLID,1,m_gridClr);
    
    m_grapgPen.CreatePen(PS_SOLID,1,m_graphColor);
    
    
    return TRUE;
}




void CWndGraph::CloseThreadsStuff()
{
    ::SetEvent(m_hLeavePaint);
    ::SetEvent(m_halive);
    ::Sleep(1000);
    ::WaitForSingleObject(m_hthread,10000);
    ::CloseHandle(m_halive);
    ::CloseHandle(m_hLeavePaint);
    delete m_pCDC;
}


BOOL CWndGraph::UseThreads()
{
    if(m_hthread == 0)
    {
        m_hLeavePaint  = ::CreateEvent(0,0,0,0);
        m_halive  = ::CreateEvent(0,0,0,0);
        m_pCDC    =  new CClientDC(this);

        //m_hdc     = ::GetDC(m_hWnd);//m_pCDC->GetSafeHdc();
        m_hdc     = m_pCDC->GetSafeHdc();
        DWORD dw;
        m_hthread =	CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)PainterThread,this,0,&dw); 
        SetThreadPriority(m_hthread,THREAD_PRIORITY_BELOW_NORMAL);
    }
    return TRUE;
}

void CWndGraph::SetBkColor(COLORREF clrBack)
{
    HBRUSH hbr = ::CreateSolidBrush(clrBack);
    HBRUSH  hbrOld = (HBRUSH)::SetClassLong(m_hWnd,GCL_HBRBACKGROUND,(LONG)hbr);
    ::DeleteObject(hbrOld);
    if((HGDIOBJ)m_delPen)
        m_delPen.DeleteObject();
    m_delPen.CreatePen(PS_SOLID,1,clrBack);	
}


BOOL CWndGraph::RegisterGraphClass()
{
    m_pWndNameG = AfxRegisterWndClass(CS_DBLCLKS |CS_OWNDC|CS_HREDRAW|CS_VREDRAW,0,
									(HBRUSH)GetStockObject(BLACK_BRUSH));
    return TRUE;	
}


void CWndGraph::GridIt(CDC *pDC)
{
    pDC->SetMapMode(MM_ANISOTROPIC);    
    pDC->SetWindowOrg(0,0);
    pDC->SetViewportOrg(0, 0);
    pDC->SetWindowExt(100,100);
    pDC->SetViewportExt(100, 100);

    CPen*       pOld = (CPen*)pDC->SelectObject(&m_gridPen);

    
    for(int i=0;i < m_xMax;i+=m_grdStepx)
    {
        pDC->MoveTo(i,0);
        pDC->LineTo(i,m_yMax);

    }
    for(int j=0;j < m_yMax;j+=m_grdStepy)
    {
        pDC->MoveTo(0,j);
        pDC->LineTo(m_xMax,j);

    }
    pDC->SelectObject(pOld);

    pDC->SetWindowExt(100, m_yWndEx);
    pDC->SetViewportExt(100, -m_yMax);
    pDC->SetWindowOrg(0,0);
    pDC->SetViewportOrg(0, m_yMax);

}

void CWndGraph::CoordonateIt(CDC* pDC,bool bdel)
{
    pDC->SetMapMode(MM_ANISOTROPIC);
    pDC->SetWindowOrg(0,0);
    pDC->SetViewportOrg(0, 0);
    pDC->SetWindowExt(100,100);
    pDC->SetViewportExt(100, 100);

    
    CPen*       pOld = 0;

    if(bdel)
        pOld = (CPen*)pDC->SelectObject(&m_delPen);
    else
        pOld = (CPen*)pDC->SelectObject(&m_axisPen);
        

    pDC->MoveTo(1,1);
    pDC->LineTo(m_xMax-1,1);
    pDC->LineTo(m_xMax-1,m_yMax-1);
    pDC->LineTo(1,m_yMax-1);
    

    pDC->MoveTo(0,0+m_yMax/2);
    pDC->LineTo(m_xMax,0+m_yMax/2);
    pDC->LineTo(m_xMax-9,0+m_yMax/2+3);
    pDC->MoveTo(m_xMax,0+m_yMax/2);
    pDC->LineTo(m_xMax-9,0+m_yMax/2-3);

    pDC->MoveTo(0,m_yMax-1);
    pDC->LineTo(0,1);
    pDC->LineTo(0+4,10);


    pDC->SelectObject(pOld);

    
    pDC->SetWindowExt(100, m_yWndEx);
    pDC->SetViewportExt(100, -m_yMax);
    pDC->SetWindowOrg(0,0);
    pDC->SetViewportOrg(0, m_yMax);

}


void CWndGraph::Update()
{
    CDC*     pDC= GetDC();
    GridIt(pDC);
    CoordonateIt(pDC);
    ReleaseDC(pDC);
}


void CWndGraph::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	//m_active = !m_active;
    m_mode = (++m_mode % 3);
    Invalidate(); 
	CWnd::OnLButtonDblClk(nFlags, point);
}

BOOL CWndGraph::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{
    if(m_iHooked)
        return TRUE;
    else
    return CWnd::OnSetCursor(pWnd, nHitTest, message);
}

void CWndGraph::OnMouseMove(UINT nFlags, CPoint point) 
{
    	CWnd::OnMouseMove(nFlags, point);
}

void CWndGraph::OnLButtonDown(UINT nFlags, CPoint point) 
{
    CWnd::OnLButtonDown(nFlags, point);
}

void CWndGraph::OnLButtonUp(UINT nFlags, CPoint point) 
{
    
    OnMouseMove(nFlags,  point) ;
}

BOOL CWndGraph::CreateBuffers()
{
    m_Buff1           = new WORD[MAX_BUFF];
    m_Buff2           = new WORD[MAX_BUFF];
    m_grapPtsBackBuff = new WORD[m_xMax*2];
	
	for(int i=0;i<MAX_BUFF;i++)
	{	
		*(m_Buff2+i) = *(m_Buff2+i) = 32767;
	}
   
    m_pSwitchIn       = m_Buff1;
    m_pSwitchOut      = m_Buff2;
    m_Loading         = FALSE;
    
    return TRUE;
}



void CWndGraph::SetSampleAttr(int bits, int stereo,int bps)
{
    
    m_viewscale     = m_yMax;       
    m_yWndEx        = (2 << (bits-1)); // scale y
    m_bps           = bps;
    m_sleep         = 1000 / REFRESH;
    int oneScreen   = bps/REFRESH;
    m_stepIn        = oneScreen/(m_xMax*stereo);

    for(int i=0;i<MAX_BUFF;i++)
    {
        *(m_Buff1+i) = m_yWndEx/2;
        *(m_Buff2+i) = m_yWndEx/2;
    }

    
}



void CWndGraph::ReleasePaint()
{
    m_Loading = !m_Loading;
    if(m_Loading)
    {
        m_pSwitchIn         = m_Buff2;
        m_pSwitchOut        = m_Buff1;
    }
    else
    {
        m_pSwitchIn         = m_Buff1;
        m_pSwitchOut        = m_Buff2;
    }
    m_l1      = m_lastLen;
    m_lastLen = 0;
    SetEvent(m_hLeavePaint);
}


void CWndGraph::DrawBuffers(CDC* pDC,BOOL bLastBuff)
{
    bool        bscale = false;
    int         xp    = 0;
    
    
    int         yd    = *m_grapPtsBackBuff;
    CPen*       pOld  = (CPen*)pDC->SelectObject(&m_grapgPen);
    CPen*       op    = 0;
    WORD*       pOut  = m_pSwitchOut;
    int         yp    = *pOut;

    if(m_mode > 1)
        DoFft(pOut,m_xMax);
	
	int i;
    
    for( i=1; i < m_xMax ;i++)
    {
       op = pDC->SelectObject(&m_delPen);
       Move(pDC,xp,yd,0);
       Line(pDC,i,yd = *(m_grapPtsBackBuff+i));
       pDC->SelectObject(op);
        
       Move(pDC,xp,yp,0x00FFFF00);    
       Line(pDC,i,yp = *(pOut++));
	   m_grapPtsBackBuff[i] = yp;
       xp = i ;

    }
    pDC->SelectObject(pOld);
    GdiFlush();
    m_pSwitchOut = pOut;
}
    

int  CWndGraph::PainterThread(void* pData)
{
    CWndGraph*  pObj = reinterpret_cast<CWndGraph*>(pData);
    CDC         dc;

    dc.Attach(pObj->m_hdc);
    dc.SetMapMode(MM_ANISOTROPIC);
    dc.SetWindowExt(100, pObj->m_yWndEx);
    dc.SetViewportExt(100, -pObj->m_yMax);
    dc.SetWindowOrg(0,0);
    dc.SetViewportOrg(0, pObj->m_yMax);

    int xmax    = pObj->m_xMax;
    int length  = 0;
    int grid    = 0;
    int sleep   = pObj->m_sleep;
    int contor  = 0;

 
    do{
            if( WaitForSingleObject(pObj->m_hLeavePaint,max(sleep,60)) == WAIT_OBJECT_0)
            {
                if(pObj->m_mode == 0)
                {
                    if(length > xmax * 4)
                    {
                        sleep--;
                        if(sleep < 0 )
                            sleep = 0;

                    }
                    if(length < xmax*2)
                        sleep++;
                }
            
                length = pObj->m_l1;
                

            }
            if(length > xmax)
            {
                
                Ecs();
                if((++grid & 0xF) ==0xF)  
                    pObj->GridIt(&dc);
                pObj->DrawBuffers(&dc);
                Xcs();
		        length -= xmax;

            }
            if(pObj->m_mode == 2)
                length=0;
            
    }while(WAIT_TIMEOUT == WaitForSingleObject(pObj->m_halive,0));

    dc.Detach();
    return 0;
}



void CWndGraph::DoFft(WORD* pInBuff, int length)
{
    int    i, j = 1, k, nPoints = 7, m, nPtsPow, q;
    double dTemp, dWr, dvpR, dwpI, dWi, dAlfa, dTempReal, dTempImag;
    double dMaxPick = 0;

    nPtsPow = 1 << nPoints;
    
    double dReals[256];
    double dImag[256];
    double dVect[256];

    dMaxPick = -32768;

    for(i=0; i<nPtsPow; i++)
    {
        *(dReals+i) = *(pInBuff+i) / dMaxPick;
        *(dImag+i) = 0.0f;
    }

    // bit reversal
    for (i=1; i<nPtsPow; i++)
    {
        if  (i<j)
        {
            dTempReal     = *(dReals+j-1);
            *(dReals+j-1) = *(dReals+i-1);
            *(dReals+i-1) = dTempReal;
            dTempReal     = *(dImag+j-1);
            *(dImag+j-1)  = *(dImag+i-1);
            *(dImag+i-1)  = dTempReal;
        }
        k=nPtsPow >> 1;
        while (k >=1 &&  k < j)
        {
            j-=k;
            k>>=1;
        }
        j += k;
    }

    for(m=1; m <= nPoints; m++)
    {
        k = 1 << m;
        dAlfa = -6.283185307 / k;
        dWr = 1.0f;
        dWi = 0.0f;
        dvpR = cos(dAlfa);
        dwpI = sin(dAlfa);

        for(j=1;  j<=k/2; j++)
        {
            for(i=j;  i<=nPtsPow;   i+=k)
            {
	            q=i+k/2;
	            dTempReal = dWr * (*(dReals+q-1)) - dWi * (*(dImag+q-1));
	            dTempImag = dWr * (*(dImag+q-1)) + dWi * (*(dReals+q-1));
	            *(dReals+q-1) = *(dReals+i-1) - dTempReal;
	            *(dImag+q-1) = *(dImag+i-1) - dTempImag;
	            *(dReals + i - 1) += dTempReal;
	            *(dImag+i-1) += dTempImag;
            }
            dTemp = dWr;
            dWr = dWr * dvpR - dWi * dwpI;
            dWi = dWi * dvpR + dTemp * dwpI;
        }
    }

    for(i=0;i<nPtsPow;i++)
        *(dVect+i) = (*(dReals+i) * (*(dReals+i))) + 
                     (*(dImag+i) * (*(dImag+i)));

    
    double d = 0;  
    WORD* pw = pInBuff;
    memset(pInBuff,0,sizeof(WORD)*length);
    WORD  sum = 0;

    for( i= 2; i <= nPtsPow/2-2; i++)
    {
       sum = (int)(dVect[i-1] * 200 );//+8000;
      *(pw++) = (WORD)(10000 * log10(sum))-58000;
      *(pw++) = *pw;
      if(i%3==0)
         *(pw++) = *pw;
    }
}

void CWndGraph::OnRButtonDown(UINT nFlags, CPoint point) 
{
    m_stepy+=1000;
    if(m_stepy > 12000)
        m_stepy = 1000;

	CWnd::OnRButtonDown(nFlags, point);
    Invalidate();
}

⌨️ 快捷键说明

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