Click here to Skip to main content
Click here to Skip to main content

A Spectrum Analyzer at your desktop

, 16 May 2004
Rate this:
Please Sign up or sign in to vote.
A control for charting and graphing, especially for Spectrum Analyzer.

Sample Image


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:

    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),  // Freq. Range : 100-150 MHz 
    ptRangeY(0, 120);  // Signal Strength Range: 0-120 units

CRect rect; 
// Get the rectangular coordinates of the rectangle we already placed on dialog

// Convert to the client coordinates

// remember to destroy it if it was created before
if (m_SpectrumAnalyzer_Ctrl)

// Create and place the spectrum control on screen
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.


These are the public member functions and their descriptions:

// Add a new point
void AddPoint(CPoint CurPos);

// Draw all viewable data
void DrawLine();

// Write(draw) some text on the control
void DrawText(CPoint Pos, CString szStr);

// Clear all the drawing in the control
void Clear();

// re-draw grids, re-write labels
void UpdateLabels();

// clear list of data 
void ClearList();

// return number of points in the control
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:

// Set the Callback message that control sends when
// user clicks the control to set to a frequency
m_SpectrumAnalyzer_Ctrl.SetCallbackSetToFreq(m_hWnd, WM_USER_SET_TO_FREQ); 

// Set the Callback message that control sends when user moves the mouse over control 
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.


  • First version: 10/May/2004.


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


About the Author

Mehdi Ebrahimian
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 ( or contact me to start a business! You can also find me at:

Comments and Discussions

GeneralMy vote of 3 Pinmemberbuyong7-Mar-12 21:03 
GeneralMy vote of 5 Pinmembercowg1-Jan-12 2:59 
Questionproblem with Playing Pinmembert4urean12-Aug-06 3:07 
QuestionProblem playing sound and analysing it Pinmembert4urean12-Aug-06 2:57 
I have to use a Win32 API in a C# project (VS 2K5). I want to create a API wrapper class in C++. And then use it from my C# code.
I tried to use P/Invoke in C# to create a wrapper class, some of the methods didn’t work because Pointers to memory were not working..
My project has a method that continuously reads a block of PCM data from an external radio receiver connected to the computer through USB.
Is there and way to listen to that signal through C#. IS PCM just like audio signal … if not how do I convert it into audio.
I am writing an example of the function I have to write and tell me what type of project I have to make and what procedure I have to follow.
#include "stdafx.h"
// G3 API function type declarations
typedef int (__stdcall *FNCOpenRadioDevice)(int iDeviceNum);
typedef BOOL (__stdcall *FNCCloseRadioDevice)(int hRadio);
typedef BOOL (__stdcall *FNCSetAtten)(int hRadio, BOOL fAtten);
typedef BOOL (__stdcall *FNCSetPower)(int hRadio, BOOL fPower);
typedef BOOL (__stdcall *FNCSetAGC)(int hRadio, int iAGC);
typedef BOOL (__stdcall *FNCCodecStart)(int hRadio,void (__stdcall *CallbackFunc)(void *),
void *CallbackTarget);
typedef BOOL (__stdcall *FNCCodecStop)(int hRadio);
typedef unsigned int (__stdcall *FNCCodecRead)(int hRadio,void *Buf,unsigned int Size);
typedef struct {
int hRadio;
FNCCodecRead CodecRead;
} CallbackContext;
void __stdcall CodecCallback(void *Target)
unsigned int i;
char Buf[4096];
CallbackContext *Ctx=(CallbackContext *)Target;
while ((i=Ctx->CodecRead(Ctx->hRadio,Buf,sizeof(Buf)))!=0)
//int _tmain(int argc, _TCHAR* argv[])
int main(int argc, char* argv[])
// load the G3 API library
HMODULE dll=LoadLibraryA("wrg303api.dll");
if (!dll) {puts("WRG303API.DLL not found !"); return 0;}
// link G3 API functions
FNCOpenRadioDevice OpenRadioDevice=(FNCOpenRadioDevice)GetProcAddress(dll,"OpenRadioDevice");
FNCCloseRadioDevice CloseRadioDevice=(FNCCloseRadioDevice)GetProcAddress(dll,"CloseRadioDevice");
FNCSetAtten SetAtten=(FNCSetAtten)GetProcAddress(dll,"SetAtten");
FNCSetPower SetPower=(FNCSetPower)GetProcAddress(dll,"SetPower");
FNCSetAGC SetAGC=(FNCSetAGC)GetProcAddress(dll,"SetAGC");
FNCCodecStart CodecStart=(FNCCodecStart)GetProcAddress(dll,"CodecStart");
FNCCodecStop CodecStop=(FNCCodecStop)GetProcAddress(dll,"CodecStop");
FNCCodecRead CodecRead=(FNCCodecRead)GetProcAddress(dll,"CodecRead");
// open the first available radio
int hRadio=OpenRadioDevice(0);
if (!hRadio) {puts("No WR-G303 device could be opened !");FreeLibrary(dll); return 0;}
// set Power, AGC and Attenuator
if (SetPower(hRadio,TRUE)) puts("The device is turned ON"); else puts("The device failed to turn ON");
if (SetAtten(hRadio,FALSE)) puts("The attenuator is OFF"); else puts("The attenuator failed to turn OFF");
if (SetAGC(hRadio,3)) puts("The AGC is FAST"); else puts("The AGC failed to switch");
// open the IF samples destination file
FILE *f=fopen("IF2.pcm","wb");
// start the IF stream from the codec
CallbackContext Ctx;
if (!CodecStart(hRadio,CodecCallback,&Ctx)) puts("Codec streaming couldn't be started!");
else {
puts("Codec streaming properly started!");
while (!ftell(f) )
// close the device handle
if (CloseRadioDevice(hRadio)) puts("The device is closed properly"); else puts("The device failed to close");
// free the G3 API library
return 0;
o O º(`'·.,(`'·., ☆,.·''),.·'')º O o°
»·'"`»* *☆ t4ure4n ☆* *«·'"`«
°o O º(,.·''(,.·'' ☆`'·.,)`'·.,)º O o°

Questionhow to read audio or IF data Pinmemberpsyclope2-Jun-06 2:18 
GeneralSupport needed Pinmemberalonsl2-Apr-05 10:23 
GeneralRe: Support needed Pinmembermoxjake26-Apr-05 8:23 
GeneralSir! can you help me! Pinmemberilansue21-Mar-05 21:52 
GeneralRe: Sir! can you help me! PinmemberMehdi Ebrahimian23-Mar-05 18:07 
GeneralRe: Sir! can you help me! Pinmembermssu23-Mar-05 18:57 
GeneralRe: Sir! can you help me! PinmemberMehdi Ebrahimian25-Mar-05 3:46 
GeneralMem leak + some pragmas PinmemberAlexms19-May-04 11:52 
GeneralRe: Mem leak + some pragmas PinmemberMehdi Ebrahimian21-May-04 2:41 
GeneralNice work! PinmemberA. Riazi17-May-04 2:21 
GeneralRe: Nice work! PinmemberKeuk-han. Kwon20-Mar-05 15:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150129.1 | Last Updated 17 May 2004
Article Copyright 2004 by Mehdi Ebrahimian
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid