📄 wndgraph.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 + -