Click here to Skip to main content
15,892,161 members
Articles / Desktop Programming / MFC

A Spectrum Analyzer at your desktop

Rate me:
Please Sign up or sign in to vote.
4.48/5 (22 votes)
16 May 20043 min read 115.8K   6.2K   57  
A control for charting and graphing, especially for Spectrum Analyzer.
// SpectrumAnalyzer.cpp : implementation file
//

#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_iDrawPenWidth=1;
	m_DrawPen.DeleteObject();
	m_DrawPen.CreatePen(PS_SOLID, m_iDrawPenWidth, RGB(0, 255, 0));

	m_IndicatorPen.DeleteObject();
	m_IndicatorPen.CreatePen(PS_SOLID, m_iDrawPenWidth, RGB(255, 0, 0));
	
	// 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);
		
	TRACE(_T("InvalidateCtrl()"));
	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;
	TRACE(_T("    DrawLine()"));
	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
	
	BOOL 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
	
	TRACE(_T("    Clear()"));
	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!
	
	if ((dwFlags&MK_CONTROL)!=MK_CONTROL)
		return;
	
	CPoint *ptCur;
	ptCur = new CPoint;  // this pointer is deleted in CScanDialog::OnSetToFreq
	*ptCur = MapViewToAxis(pos);
	*ptCur = MapAxisToPoint(*ptCur);
	
	SendCallback(1, WPARAM(ptCur), 0);

}

CPoint CSpectrumAnalyzer::MapPointToAxis(const CPoint pos)
{
	// A Point comes from frequency changer or something else!
	// Point.x is in the range: m_RangeX.x and m_RangeX.y
	// Point.y is in the range: m_RangeY.x and m_RangeY.y
	// a point should be converted to Axis values, that is in screen/control coordinates
	// but all points in the control are not viewable, some are in viewable area and the others are not
	// Scrolling or Zooming, changes this viewable area

	// function MapPointToAxis, maps a point to Axis values
	// function MapAxisToView maps a point in Axis scale to View scale (their scales differ in that, Axis also contains the margins)
	// a point after mapping to view scale, may not be viewable, so a Bool variable identifies if it is viewable or not
	// if that was viewable, the draw it!
	
	CPoint retPos;
	retPos.x = int (m_fHAxisScale * (pos.x - m_RangeX.x));
	retPos.y = int (m_fVAxisScale * (pos.y - m_RangeY.x));

	return retPos;
	
}

CPoint CSpectrumAnalyzer::MapAxisToPoint(const CPoint pos)
{
	// refer to comments in MapPointToAxis function

	CPoint retPos;
	retPos.x = int (pos.x / m_fHAxisScale) + m_RangeX.x;
	retPos.y = int (pos.y / m_fVAxisScale) + m_RangeY.x;

	return retPos;
	
}

BOOL CSpectrumAnalyzer::MapAxisToView(CPoint &pos)
{
	// refer to comments in MapPointToAxis function

	// if the point is ready to be drawn, return true.
	// this is only true if point is within the range of View

	BOOL retBool=FALSE;
	if ( (pos.x>=m_ViewTopLeft.x) && (pos.x<=m_ViewTopLeft.x+m_iClientWidth) )
	{
		if ( (pos.y>=m_ViewTopLeft.y) && (pos.y<=m_ViewTopLeft.y+m_iClientHeight))
			retBool = TRUE;
	}
	
	pos.x-=m_ViewTopLeft.x;
	pos.y-=m_ViewTopLeft.y;

	pos.x = int ( m_fHViewScale * pos.x + m_iLeftMargin);
	pos.y = int ( m_fVViewScale * pos.y + (m_iClientHeight - m_iBotMargin));

	return retBool;
}

CPoint CSpectrumAnalyzer::MapViewToAxis(const CPoint pos)
{
	// refer to comments in MapPointToAxis function

	// if the point is ready to be drawn, return true.
	// this is only true if point is within the range of View

	CPoint retPos = pos;

	retPos.x = int ( (pos.x - m_iLeftMargin) /m_fHViewScale);
	retPos.y = int ( (pos.y - (m_iClientHeight - m_iBotMargin)) / m_fVViewScale);
	
	retPos.x+=m_ViewTopLeft.x;
	retPos.y+=m_ViewTopLeft.y;
	
	return retPos;
		
}

void CSpectrumAnalyzer::HorizScroll(BOOL bIfToLeft /* = FALSE */, int iScrollAmount /* = 0 */)
{
	// Scroll Horizontally
	// Here, I'm clearing all the contents and re-drawing;
	// maybe we can use screen memory copy functions to do it faster!

	Clear();

	int iActualScroll=0;

	int iIncDec= int(m_iClientWidth/2);
	if (iScrollAmount>0)
		iIncDec = iScrollAmount;
	if (bIfToLeft){
		if (m_ViewTopLeft.x)
		{
			if (m_ViewTopLeft.x-iIncDec>=0)
			{
				m_ViewTopLeft.x-=iIncDec;
				iActualScroll = -iIncDec;
			}
			else
			{
				iActualScroll=-m_ViewTopLeft.x;
				m_ViewTopLeft.x =0;
			}
		}
	}
	else{
		if (m_ViewTopLeft.x<m_iMaxHAxis)
		{
			if (m_ViewTopLeft.x + iIncDec<= m_iMaxHAxis)
			{
				m_ViewTopLeft.x += iIncDec;		
				iActualScroll=iIncDec;
			}
			else
			{
				iActualScroll = m_iMaxHAxis-m_ViewTopLeft.x;
				m_ViewTopLeft.x=m_iMaxHAxis;
			}
		}		
	}

	UpdateLabels();
	DrawLine();	
	
	m_iHScrollPos +=iActualScroll;
	SetScrollPos (SB_HORZ, m_iHScrollPos, TRUE);

}

void CSpectrumAnalyzer::UpdateLabels()
{
	// Draw Grids and Labels

	if(!m_pMemDC->GetSafeHdc())
		return;

	//Select a specified pen to the device context to draw background lines
	CPen bkLinesPen;
	if(!bkLinesPen.CreatePen(PS_SOLID, 1, m_crGrids))
		return;

	if(!m_pMemDC->SelectObject(bkLinesPen))
		return;
	
	CPoint LabelLoc;
	CString chLabel;

	CPoint ptLocPoint;

	int iRightExtent; // horizontal lines should be drawn up to last vertical line, not more!

	// Vertical Lines, Horizontal Labels
	byte iLabelCounter=0;
	for (int iHorValue = m_RangeX.x; iHorValue <= m_RangeX.y; iHorValue+=m_iHLabelSpacing )
	{
		ptLocPoint = CPoint(iHorValue, m_RangeY.x); // y is dummy now
		
		ptLocPoint = MapPointToAxis(ptLocPoint);
		ptLocPoint.y = m_ViewTopLeft.y;  // y is dummy, but change it so that MapAxisToView function works properly
		
		if (!MapAxisToView(ptLocPoint))
			continue;

		LabelLoc = CPoint(ptLocPoint.x, m_iClientHeight - m_iBotMargin + 2);
		
		if (!iLabelCounter++)
		{
			chLabel.Format(_T("% 4.2f"), double(iHorValue) / double(m_iHLabelValueScale)	);
			DrawText(LabelLoc, chLabel);
			
			m_pMemDC->MoveTo(ptLocPoint.x, m_rcClient.top + m_iTopMargin);
			m_pMemDC->LineTo(ptLocPoint.x, m_rcClient.bottom - m_iBotMargin + 4);
		
		}
		else
		{
			m_pMemDC->MoveTo(ptLocPoint.x, m_rcClient.top + m_iTopMargin);
			m_pMemDC->LineTo(ptLocPoint.x, m_rcClient.bottom - m_iBotMargin + 2);
		}

		iRightExtent = ptLocPoint.x;


		if (iLabelCounter==m_iHLabelDistance)
			iLabelCounter=0;			
	}
	
	// determining iRightExtent
	ptLocPoint = CPoint(m_RangeX.y, m_RangeY.x); // y is dummy now
	
	ptLocPoint = MapPointToAxis(ptLocPoint);
	ptLocPoint.y = m_ViewTopLeft.y;  // y is dummy, but change it so that MapAxisToView function works properly
	
	if (!MapAxisToView(ptLocPoint)) // last point is out of view
		iRightExtent = m_rcClient.right - m_iRightMargin;
	
	// Horizontal Lines, Vertical Labels
	
	for (int iVertValue = 0; iVertValue <= m_RangeY.y; iVertValue+=m_iVLabelSpacing)
	{
		ptLocPoint = CPoint(m_RangeX.x, iVertValue); // x is dummy now
		
		ptLocPoint = MapPointToAxis(ptLocPoint);
		ptLocPoint.x = m_ViewTopLeft.x;  // x is dummy, but change it so that MapAxisToView function works properly
		MapAxisToView(ptLocPoint);

		LabelLoc = CPoint(2, ptLocPoint.y-6);
		
		char chTemp[20];
		itoa(iVertValue, chTemp, 10);
		chLabel = (LPCSTR) chTemp;
		
		DrawText(LabelLoc, chLabel);

		m_pMemDC->MoveTo(m_rcClient.left + m_iLeftMargin-2, ptLocPoint.y);
		m_pMemDC->LineTo(iRightExtent, ptLocPoint.y);
		
	}

}

void CSpectrumAnalyzer::OnHScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar )
{

	switch (nSBCode)
	{
		case SB_LINELEFT:
			HorizScroll(TRUE, m_iHScrollShift);
			break;
		case SB_LINERIGHT:
			HorizScroll(FALSE, m_iHScrollShift);
			break;
		case SB_PAGELEFT:
			HorizScroll(TRUE, 5*m_iHScrollShift);
			break;
		case SB_PAGERIGHT:
			HorizScroll(FALSE, 5*m_iHScrollShift);
			break;
		default:
			break;
	}

}

void CSpectrumAnalyzer::OnMouseMove( UINT nFlags, CPoint point )
{
	
	// send address of the point to message handler of ScanDialog to show it on screen

	CPoint *ptCur;
	ptCur = new CPoint;
	*ptCur = MapViewToAxis(point);
	*ptCur = MapAxisToPoint(*ptCur);
	
	if ((ptCur->x > m_RangeX.y) || (ptCur->x < m_RangeX.x) )
		return;
	
	SendCallback(2, WPARAM(ptCur), 0);
	
}

void CSpectrumAnalyzer::ReSetStep(BOOL bDoZoomOut)
{
	// re-set the variables and re-draw the chart
	// used for Zooming in and out

	if (bDoZoomOut)  
	{
		m_iHLabelSpacing *= 2;
		if (m_iHLabelSpacing > ( DWORD((m_RangeX.y - m_RangeX.x ) / m_iNumVGridLines ) ))
			m_iHLabelSpacing = DWORD((m_RangeX.y - m_RangeX.x ) / m_iNumVGridLines ) ;
	}
	else
	{
		m_iHLabelSpacing /= 2;
		if (m_iHLabelSpacing < 1000)
			m_iHLabelSpacing = 1000;
	}

	m_ViewTopLeft = CPoint(0,0);
		
	m_iMaxVAxis = m_iClientHeight;

	SetRangeX(m_RangeX);
	SetRangeY(m_RangeY);

	Clear();
	UpdateLabels();
	DrawLine();
    
	// Set the horizontal scrolling parameters.
    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);
}
void CSpectrumAnalyzer::ClearList()
{
	m_pList->RemoveAll();
}
CPoint CSpectrumAnalyzer::GetNextPoint(POSITION &NewPos)
{
	// gives the next point in the list
	// used for saving the list 

	CPoint retPoint(-1,-1);  // determines no point in the list!
	
	if (&NewPos==NULL) // nothing exists in the list
		return retPoint;

	retPoint = m_pList->GetNext(NewPos);
	return retPoint;		
}

// This function sets the callback message that will be sent to the
// specified window each time user sets to a new frequency
//
// Parameters:
//		[IN]	hWnd
//				Handle of the window that will receive the callback message.
//				Pass NULL to remove any previously specified callback message.
//		[IN]	nMessage
//				Callback message to send to window.
//		[IN]	wParam
//				First 32 bits user specified value that will be passed to the callback function.
//		[IN]	lParam
//				Second 32 bits user specified value that will be passed to the callback function.
//
// Remarks:
//		the callback function must be in the form:
//		LRESULT On_ChangeCallback(WPARAM wParam, LPARAM lParam)
//		Where:
//				[IN]	wParam
//						First 32 bits user specified value.
//				[IN]	lParam
//						Second 32 bits user specified value.
//
// Return value:
//		KNOBCONTROLST_OK
//			Function executed successfully.
//
void CSpectrumAnalyzer::SetCallbackSetToFreq(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam)
{
	// Set Callback function's parameters for when WM_USER_SET_TO_FREQ message is invoked by CSpectrumAnalyzer
	// Note No. 13830203-5

	m_csCallbackSetToFreq.hWnd = hWnd;
	m_csCallbackSetToFreq.nMessage = nMessage;
	m_csCallbackSetToFreq.wParam = wParam;
	m_csCallbackSetToFreq.lParam = lParam;	
}

void CSpectrumAnalyzer::SetCallbackShowFreq(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam)
{
	// Set Callback function's parameters for when WM_USER_SHOW_CURRENT_FREQ message is invoked by CSpectrumAnalyzer 
	m_csCallbackShowFreq.hWnd = hWnd;
	m_csCallbackShowFreq.nMessage = nMessage;
	m_csCallbackShowFreq.wParam = wParam;
	m_csCallbackShowFreq.lParam = lParam;
	
}
void CSpectrumAnalyzer::SendCallback(int iCallbackIndex, WPARAM wParam, LPARAM lParam)
{
	// Send callback message to parent window
	// iCallbackIndex == 1 ---------------> SetToFreq Callback
	// iCallbackIndex == 2 ---------------> ShowFreq Callback

	// Note No. 13830203-5
	if (iCallbackIndex==1)
		::PostMessage(m_csCallbackSetToFreq.hWnd, m_csCallbackSetToFreq.nMessage, wParam, lParam);
	else
		::PostMessage(m_csCallbackShowFreq.hWnd, m_csCallbackShowFreq.nMessage, wParam, lParam);
}
void CSpectrumAnalyzer::DrawPieceOfLine(CPoint ptStart, CPoint ptEnd)
{
	if (ptStart.y <= m_iVHighIndicatorView)
	{
		// start point is in HIGH region
		if (ptEnd.y <= m_iVHighIndicatorView)
		{
			// both points are in HIGH region
			m_pMemDC->SelectObject(m_IndicatorPen);
			m_pMemDC->MoveTo(ptStart);
			m_pMemDC->LineTo(ptEnd);			
		}
		else
		{
			// Start point is in high region, but not the other
			CPoint ptInter;
			ptInter.y = m_iVHighIndicatorView;
			ptInter.x = (m_iVHighIndicatorView - ptStart.y) * (ptEnd.x - ptStart.x) / (ptEnd.y - ptStart.y) + ptStart.x;
			
			m_pMemDC->SelectObject(m_IndicatorPen);
			m_pMemDC->MoveTo(ptStart);
			m_pMemDC->LineTo(ptInter);

			m_pMemDC->SelectObject(m_DrawPen);
			m_pMemDC->MoveTo(ptInter);
			m_pMemDC->LineTo(ptEnd);
		}
	}
	else
	{
		if (ptEnd.y > m_iVHighIndicatorView )
		{
			// neither points are in HIGH region
			m_pMemDC->SelectObject(m_DrawPen);
			m_pMemDC->MoveTo(ptStart);
			m_pMemDC->LineTo(ptEnd);			
		}
		else
		{
			// End point is in HIGH region, but not the start point
			CPoint ptInter;
			ptInter.y = m_iVHighIndicatorView;
			ptInter.x = (m_iVHighIndicatorView - ptStart.y) * (ptEnd.x - ptStart.x) / (ptEnd.y - ptStart.y) + ptStart.x;
						
			m_pMemDC->SelectObject(m_DrawPen);
			m_pMemDC->MoveTo(ptStart);
			m_pMemDC->LineTo(ptInter);

			m_pMemDC->SelectObject(m_IndicatorPen);
			m_pMemDC->MoveTo(ptInter);
			m_pMemDC->LineTo(ptEnd);
		}
	}
}
void CSpectrumAnalyzer::SetVHighIndicator(int iVHighIndicator)
{
	m_iVHighIndicator = iVHighIndicator;
	
	// convert m_iVHighIndicator that is in RangeY scale, to View scale
	CPoint ptLocPoint = CPoint(m_RangeX.x, m_iVHighIndicator); // x is dummy now
		
	ptLocPoint = MapPointToAxis(ptLocPoint);
	ptLocPoint.x = m_ViewTopLeft.x;  // x is dummy, but change it so that MapAxisToView function works properly
	MapAxisToView(ptLocPoint);
	m_iVHighIndicatorView = ptLocPoint.y;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Iran (Islamic Republic of) Iran (Islamic Republic of)
I graduated from Sharif university of technology, Mastering Electrical/Telecommunications. I enjoyed computer programming since I was at high-school, so I kept on updating my knowledge on software while working in the field of telecom. Now, I'm a system integrator and a software manager. I cooperate with several companies and yet have my own company. Now we are active in both rfid and image processing in the company.
Do not hesitate to see my own website (www.ebrahimian.ir) or contact me to start a business! You can also find me at:
www.tolue.ir
www.rfid.ir

Comments and Discussions