Introduction
Recently I was working in a project in which I had to draw data from a radio (or a spectrum analyzer). I reviewed all charting controls in CodeProject but none seemed to be useful for me. So, I managed to code it myself. In addition to simple charting, this controls also supports Zoom In/Out and scrolling. One can also discriminate higher data by another color as is seen in the picture.
Using the code
First of all, place a Picture control on your dialog. Change its ID to IDC_SPECTRUM_STATIC
and its type from Frame
to Rectangle
. Change control's width and height to make it fit. This control will be created at run-time. Add #Include "SpectrumAnalyzer.h";
to your dialog's header file. Add a member variable to dialog for this control:
public:
CSpectrumAnalyzer m_SpectrumAnalyzer_Ctrl;
Now, place this piece of code wherever you want to create the control:
DWORD m_iStartFreq = 100000000,
m_iStopFreq = 150000000;
CPoint ptRangeX(m_iStartFreq, m_iStopFreq),
ptRangeY(0, 120);
CRect rect;
GetDlgItem(IDC_SPECTRUM_STATIC)->GetWindowRect(rect);
ScreenToClient(rect);
if (m_SpectrumAnalyzer_Ctrl)
m_SpectrumAnalyzer_Ctrl.Destroy();
m_SpectrumAnalyzer_Ctrl.Create(rect, this, IDC_SPECTRUM_STATIC, ptRangeX, ptRangeY);
The control is simply created by the above statements. ptRangeX
defines horizontal bounds and ptRangeY
defines vertical bounds.
Features
These are the public member functions and their descriptions:
void AddPoint(CPoint CurPos);
void DrawLine();
void DrawText(CPoint Pos, CString szStr);
void Clear();
void UpdateLabels();
void ClearList();
int GetPointCount() { return m_pList->GetCount();}
Deep Inside
Using a doubly-linked list to maintain data, the control determines which data points should be drawn (considering scroll position) and draws them.
The control defines three different scales: Actual data (point), Axis and View. Any data you provide is in the scales provided by ptRangeX
and ptRangeY
. The size of the control you place on dialog determines Axis scale. But, as is seen in the picture, user can define margins for top, bottom, left and right for the grids in the control. This defines View scale. So, any data you add to the list, should pass two stages to get drawn: conversion from Point to Axis (by MapPointToAxis()
function), and conversion from Axis to View scale (by MapAxisToView()
function).
In addition, you can change the color of background, grid, text, drawing pen and high-region pen by changing these variables in the constructor: m_crBackGround
, m_crGrids
, m_crText
, m_crDrawPen
and m_crIndicatorPen
.
Advanced Features
Because this control was mainly written to be used as a receiver software, there are some extra features in it. You can highlight above-threshold data by using SetVHighIndicator()
function.
Control can also send callback messages to parent dialog. Control sends WM_USER_SET_TO_FREQ
message whenever user wants to set the radio to a new frequency by left-clicking the mouse while CTRL key is held. WM_USER_SHOW_CURRENT_FREQ
message is sent when user moves the mouse over the control. You may want to use this message to show frequency at the pointer.
Use these functions to set callback functions to those messages:
m_SpectrumAnalyzer_Ctrl.SetCallbackSetToFreq(m_hWnd, WM_USER_SET_TO_FREQ);
m_SpectrumAnalyzer_Ctrl.SetCallbackShowFreq(m_hWnd, WM_USER_SHOW_CURRENT_FREQ);
where m_hWnd
is the handle to the window that gets the messages.
How to improve?
One can revise the drawing section to improve speed. I think scrolling section is not wise, because it simply re-draws all the content in the window. One can use some API functions that "move" that portion of the image that is not changed by scrolling. Also, some function is needed for vertical scrolling. I have not written it here.
History
- First version: 10/May/2004.