Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

GDI+ Plot ActiveX Control

0.00/5 (No votes)
5 Sep 2013 1  
GDI+ 2D plot ActiveX control

GitHub 

The latest source code can be checked out from GitHub (https://github.com/xiangzhai/gdiplusplot).

Introduction

This is a simple OCX control, which allows you to plot two-dimensional data. Despite ProEssentials developed by Gigasoft Co., Ltd, there is no out-of-the-box control that provides simple and straightforward 2D data visualization based on GDI+. The NtGraph ActiveX control by Nikolai Teofilov (http://www.codeproject.com/KB/miscctrl/ntgraph_activex.aspx) inspired me to write my own control, mostly because I wanted to customize the source code when needed. Over time, the functionality of the ActiveX control became more elaborate, and finally I made a decision to publish what I have in hand under LGPL v3 license.

What Can It Do?

The control is able to plot a large number of points and update one or more plots on the graph with new data, replacing the old plot with the new plot. Multiple plots with individual properties such as color, visible could be customized at runtime.

How To Use the Control 

To use this OCX control, embed it in an application that supports the use of OCX controls. Microsoft Visual Basic applications, Office applications and applications created with the Microsoft Developer Studio's AppWizard can support the use of OCX controls. There are two files required to use this control. They are:

  • GDIPlusPlot.ocx——The GDIPlusPlot controls code and data
  • gdiplus.dll——The GDI+ dynamic linker library by Microsoft

Before the ActiveX control can be used in your application, it must be registered as a COM Component in the system registry. This is a self registering control. This means that to register the control in the system registry, you only need to have an application load the control and call the control's exported function DllRegisterServer. You can use the REGSVR32 utility or have your setup program do this.

How to Use the REGSVR32 Utility?

Copy GDIPlusPlot.ocx to your directory and type:
regsvr32 GDIPlusPlot.ocx
regsvr32 /u GDIPlusPlot.ocx (Unregister server)

Customizing the Control

You can include the control in your project by following the standard steps for ActiveX controls:

  1. Create MFC Dialog project or MDI/SDI project with View class derived from CFormView
  2. Choose menu Project|Add To Project|Components and Controls...
  3. Open the Registered ActiveX Control gallery
  4. Choose the GDIPlusPlot Control and click Insert 
  5. Visual C++ will generate the class CGDIPlusPlot
  6. Then you can define variable of the type as CGDIPlusPlot

Using the Code

HelloWorld example (here m_GDIPlusPlot1 is the on-the-fly realtime control and m_GDIPlusPlot2 is the static control):

BOOL CHelloWorldDlg::OnInitDialog()
{
    int RANGE_MIN = -10;
    int RANGE_MAX = 10;
    unsigned int i;

    ......
    	
    // TODO: Initial realtime GDIPlusPlot
    m_GDIPlusPlot1.SetXTime(TRUE);
    m_GDIPlusPlot1.SetCaption("RealTime");
    m_GDIPlusPlot1.AddElement(0);   // 0 stands for Gdiplus::Color Green ARGB
    m_GDIPlusPlot1.AddElement(2);   // 2 stands for Blue
    
    // NOTE: There are some APIs to set the X/Y axis label, but I decide to draw 
    // the full rcBounds size ActiveX control, so comment the drawing 
    // X/Y axis label routine

    // TODO: Initial static GDIPlusPlot
    m_GDIPlusPlot2.SetXTrack(TRUE); 	// Set X track mode a red cursor 
				// following the mouse cursor
    m_GDIPlusPlot2.AddElement(3);
    m_GDIPlusPlot2.AddElement(4);
    m_GDIPlusPlot2.AddElement(0);
    // TODO: Loading the static random datas into static GDIPlusPlot
    for (i = 0; i < 168; i++) 
    {
        int randv = (((double) rand() / 
                         (double) RAND_MAX) * RANGE_MAX + RANGE_MIN);
	m_GDIPlusPlot2.PlotXY(i, randv, 0);
	m_GDIPlusPlot2.PlotXY(i, randv / 1.6, 1);
	m_GDIPlusPlot2.PlotXY(i, sin(randv), 2);
    }

    // TODO: Set a timer for loading datas into realtime GDIPlusPlot
    SetTimer(1, 100, NULL);
    
    ......	
}

void CHelloWorldDlg::OnTimer(UINT nIDEvent) 
{
    int RANGE_MIN = -6;
    int RANGE_MAX = 6;
    int randv = (((double) rand() / 
                         (double) RAND_MAX) * RANGE_MAX + RANGE_MIN);

    // TODO: Loading the on-the-fly data into realtime GDIPlusPlot
    m_GDIPlusPlot1.PlotY(randv, 0);
    m_GDIPlusPlot1.PlotY(randv * 3, 1);
	
    ......
}

GDIPlusPlot Properties

BSTR caption;
boolean xTime;
BSTR xLabel;
BSTR yLabel;
short interval;
BSTR annolabel;
boolean xTrack;

Methods

void PlotXY(double xValue, double yValue, short index);
void SetRange(double xMin, double xMax, double yMin, double yMax);
void PlotY(double newValue, short index);
void ClearGraph();
void AddElement(short color);
void IsElementVisible(short index, boolean visible);
void SetXCursorPos(double xValue);
double GetQuadrantWidth();

Points of Interest 

The NtGraph ActiveX control based on GDI by Nikolai Teofilov inspired me to write my own control, mostly because I wanted to customize the source code when needed, so I have fun with GDI+ ^_^. 

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