📄 spectrumanalyzer.cpp
字号:
// SpectrumAnalyzer.cpp : implementation file
//
// Written by : Mehdi Ebrahimian (mebrahimian[AT]yahoo.com)
// Version: 10/May/2004
#include "stdafx.h"
#include "SpectrumAnalyzer.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CSpectrumAnalyzer
CSpectrumAnalyzer::CSpectrumAnalyzer()
{
// for a description on each variable, goto .h of file
m_pMemDC = NULL;
m_pList=NULL;
m_crBackGround = RGB(0, 0, 0);
m_crGrids = RGB(0, 130, 66);
m_crText = RGB(255, 255, 0);
m_crDrawPen = RGB(0, 255, 0);
m_crIndicatorPen = RGB(255, 0, 0);
m_iDrawPenWidth=1;
m_DrawPen.DeleteObject();
m_DrawPen.CreatePen(PS_SOLID, m_iDrawPenWidth, m_crDrawPen);
m_IndicatorPen.DeleteObject();
m_IndicatorPen.CreatePen(PS_SOLID, m_iDrawPenWidth, m_crIndicatorPen);
// margins for drawing grid and etc in the control
m_iTopMargin = 14;
m_iBotMargin = 20;
m_iLeftMargin = 24;
m_iRightMargin = 8;
m_iNumVGridLines = 10;
m_iNumHGridLines = 6;
m_iHScrollShift = 10;
// Spacing between grid lines; this is for best resolution (dippest zoom-in)
m_iHLabelSpacing = 50000;
m_iVLabelSpacing = 20; // draw labels each 20 points
m_iHLabelValueScale = 1000000; // show hor. labels at most each 100000 Hz
m_iHLabelDistance = 3;
m_iVHighIndicator = 80; // mark higher than it as HIGH region!
}
CSpectrumAnalyzer::~CSpectrumAnalyzer()
{
if(m_pMemDC)
delete m_pMemDC;
if(m_pList)
delete m_pList;
}
/////////////////////////////////////////////////////////////////////////////
// CSpectrumAnalyzer message handlers
BEGIN_MESSAGE_MAP(CSpectrumAnalyzer, CWnd)
//{{AFX_MSG_MAP(CSpectrumAnalyzer)
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_MOUSEMOVE()
ON_WM_HSCROLL()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CSpectrumAnalyzer member functions
BOOL CSpectrumAnalyzer::Create(const RECT &rect, CWnd *pParentWnd, UINT uID, CPoint m_RangeX, CPoint YRange)
{
//Postcondition:
// Creates a window within the "rect" region of the client screen
// Returns TRUE if the function creates the control successfully
// or FALSE if it fails.
// for a description on each variable, goto .h of file
BOOL bRet = CWnd::CreateEx(WS_EX_CLIENTEDGE,
AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW),
NULL,
WS_VISIBLE | WS_CHILD | WS_HSCROLL,
rect.left,
rect.top,
rect.right - rect.left,
rect.bottom - rect.top,
pParentWnd->GetSafeHwnd(),
(HMENU)uID);
if(!bRet)
return FALSE;
m_pMemDC = new CDC;
if(!m_pMemDC)
return FALSE;
// Note No. 13830203-4
m_pList = new CList<CPoint, CPoint&>;
if(!m_pList)
return FALSE;
m_ViewTopLeft = CPoint(0,0);
GetClientRect(m_rcClient);
m_iClientWidth = m_rcClient.right - m_rcClient.left;
m_iClientHeight = m_rcClient.bottom - m_rcClient.top;
if(!InvalidateCtrl())
return FALSE;
CFont m_TextFont;
LOGFONT lf;
ZeroMemory(&lf, sizeof(LOGFONT));
lstrcpy(lf.lfFaceName, _T("Arial"));
lf.lfHeight=14;
m_TextFont.CreateFontIndirect(&lf);
CFont *pOldFont=m_pMemDC->SelectObject(&m_TextFont);
m_pMemDC->SetTextColor(m_crText);
SetRangeX(m_RangeX);
SetRangeY(YRange);
SetVHighIndicator(m_iVHighIndicator);
UpdateLabels();
// Set the horizontal scrolling parameters.
// Note No. 13830203-3
m_iHScrollPos = 0;
SCROLLINFO si;
si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
si.nMin = 0;
si.nMax = m_iMaxHAxis;
si.nPos = m_iHScrollPos;
si.nPage = 200;
SetScrollInfo (SB_HORZ, &si, TRUE);
return TRUE;
}
BOOL CSpectrumAnalyzer::Destroy()
{
return (CWnd::DestroyWindow());
}
void CSpectrumAnalyzer::SetRangeX(const CPoint RangeX)
{
// Sets the upper and lower (limits) range
m_RangeX = RangeX;
double a, b, fViewableRange;
a = m_RangeX.y - m_RangeX.x;
b = m_iClientWidth;
fViewableRange = m_iNumVGridLines * m_iHLabelSpacing;
m_iMaxHAxis = int (a*b/fViewableRange);
a = m_iMaxHAxis;
b = m_RangeX.y-m_RangeX.x;
m_fHAxisScale = a/b;
a=(m_iClientWidth - m_iRightMargin)-m_iLeftMargin;
b= m_iClientWidth;
m_fHViewScale = a/b;
}
void CSpectrumAnalyzer::SetRangeY(const CPoint RangeY)
{
// Sets the upper and lower (limits) range
m_RangeY=RangeY;
m_iMaxVAxis = m_iClientHeight;
double a = m_iMaxVAxis, b = m_RangeY.y - m_RangeY.x;
m_fVAxisScale = a/b;
a = m_iTopMargin - (m_iClientHeight - m_iBotMargin);
b = m_iClientHeight;
m_fVViewScale = a/b;
}
void CSpectrumAnalyzer::DrawText(CPoint Pos, CString szStr)
{
if(!m_pMemDC->GetSafeHdc())
return;
m_pMemDC->TextOut(Pos.x, Pos.y, szStr);
CRect rcInv(m_rcClient.left, m_rcClient.top, m_rcClient.right, m_rcClient.bottom);
InvalidateRect(rcInv);
}
BOOL CSpectrumAnalyzer::InvalidateCtrl()
{
//Postcondition:
// Paints the entire client area of the control
// Returns TRUE if it's done successfuly or FALSE if it fails
CClientDC dc(this);
if(m_pMemDC->GetSafeHdc())
return FALSE;
if(!m_pMemDC->CreateCompatibleDC(&dc))
return FALSE;
m_pMemDC->SetBkColor(m_crBackGround);
CBitmap bmp;
if(!bmp.CreateCompatibleBitmap(&dc, m_rcClient.Width(), m_rcClient.Height()))
return FALSE;
if(!m_pMemDC->SelectObject(bmp))
return FALSE;
//Set the background color of the control
CBrush bkBrush;
if(!bkBrush.CreateSolidBrush(m_crBackGround))
return FALSE;
m_pMemDC->FillRect(m_rcClient, &bkBrush);
//Select a specified pen to the device context to draw background lines
CPen bkLinesPen;
if(!bkLinesPen.CreatePen(PS_SOLID, 1, m_crGrids))
return FALSE;
if(!m_pMemDC->SelectObject(bkLinesPen))
return FALSE;
InvalidateRect(m_rcClient);
return TRUE;
}
void CSpectrumAnalyzer::OnPaint()
{
CPaintDC dc(this);
if(m_pMemDC->GetSafeHdc())
dc.BitBlt(0, 0, m_rcClient.Width(), m_rcClient.Height(), m_pMemDC, 0, 0, SRCCOPY);
}
void CSpectrumAnalyzer::DrawLine()
{
//Postcondition:
// Draws the spectrum within the client area of the control
int j;
if(!m_pMemDC->GetSafeHdc())
return;
if (m_pList->GetCount()<=1)
return; // nothing to draw!
m_pMemDC->SelectObject(m_DrawPen);
// go to first point to draw from
POSITION pos = m_pList->GetHeadPosition();
CPoint pt1, pt2;
for (j = 0; j < m_pList->GetCount(); j++)
{
switch (GetPairOfPoints(pt1, pt2, pos))
{
case 0:
DrawPieceOfLine(pt1, pt2);
break;
case 1:
{
// pt2 is out of viewable region, but we must draw a line to it to
// make the curve seem continous
// do not draw in Marginal region, so interpolate!
CPoint ptInter;
ptInter.x = m_iClientWidth - m_iRightMargin;
if (pt1.x != pt2.x)
ptInter.y = ( (ptInter.x - pt1.x) * (pt1.y - pt2.y) / (pt1.x - pt2.x) ) + pt1.y;
else
ptInter.y = (pt1.y + pt2.y) /2;
DrawPieceOfLine(pt1, ptInter);
}
break;
case 2:
{
// pt1 is out of viewable region, but we must draw a line to it to
// make the curve seem continous
// do not draw in Marginal region, so interpolate!
CPoint ptInter;
ptInter.x = m_iLeftMargin;
if (pt1.x != pt2.x)
ptInter.y = ( (ptInter.x - pt1.x) * (pt1.y - pt2.y) / (pt1.x - pt2.x) ) + pt1.y;
else
ptInter.y = (pt1.y + pt2.y) /2;
DrawPieceOfLine(ptInter, pt2);
}
break;
case 3:
break;
case 4:
break;
default:
break;
}
}
CRect rcInv(m_rcClient.left, m_rcClient.top, m_rcClient.right, m_rcClient.bottom);
InvalidateRect(rcInv);
}
BYTE CSpectrumAnalyzer::GetPairOfPoints(CPoint &pt1, CPoint &pt2, POSITION &pos)
{
// gets two points from List: pt1 is at position "next to" pos and pt2 is the next point
// return value:
// 0 : both are in viewable region
// 1 : first is in viewable region , but the second one is not
// 2 : first is not in viewable reg, but the second one is
// 3 : both are not in viewable reg., or both don't exist
// 4 : the second one does not exist!
if (pos==NULL) // both do not exist
return 3;
BOOL bViewable1=FALSE, bViewable2=FALSE;
pt1 = m_pList->GetNext(pos);
pt1 = MapPointToAxis( pt1 );
if (MapAxisToView(pt1))
bViewable1 = TRUE;
if (pos == NULL) // second point does not exist
return 4;
pt2 = m_pList->GetNext(pos);
pt2 = MapPointToAxis( pt2 );
if (MapAxisToView(pt2))
bViewable2 = TRUE;
CPoint ptDummy;
if (pos == NULL)
pos = m_pList->GetTailPosition();
else
ptDummy = m_pList->GetPrev(pos); // so that pos points to pt1 for future call of function
BYTE retByte;
if (bViewable1)
{
if (bViewable2)
retByte = 0;
else
retByte = 1;
}
else
{
if (bViewable2)
retByte = 2;
else
retByte = 3;
}
return retByte;
}
void CSpectrumAnalyzer::AddPoint(CPoint CurPos)
{
//ASSERT(NewPos.x <= m_RangeX.y && NewPos.x >= m_RangeY.x && NewPos.y<=m_RangeY.y && NewPos.y>=m_RangeY.x);
CPoint NewPos=CurPos;
if ( NewPos.x<m_RangeX.x)
NewPos.x=m_RangeX.x;
if (NewPos.x>m_RangeX.y)
NewPos.x=m_RangeX.y;
if ( NewPos.y<m_RangeY.x)
NewPos.y=m_RangeY.x;
if (NewPos.y>m_RangeY.y)
NewPos.y=m_RangeY.y;
m_pList->AddTail(NewPos);
return;
}
void CSpectrumAnalyzer::Clear()
{
// Clear the client area
if(!m_pMemDC->GetSafeHdc())
return;
//Set the background color of the control
CBrush bkBrush;
if(!bkBrush.CreateSolidBrush(m_crBackGround))
return;
m_pMemDC->FillRect(m_rcClient, &bkBrush);
InvalidateRect(m_rcClient);
}
void CSpectrumAnalyzer::OnLButtonDown( UINT dwFlags, CPoint pos)
{
// send a message to parent to set the radio to a newer frequency
// but only if not scanning!
// user should hold CTRL key for this option to act!
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -