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

C2DPushGraph: A Push Graph Control

By , 15 Jan 2008
 

Introduction

Some of you may have already come to realize I have previously written and released a similar control via CodeProject. Even though the last control was written using C++ along with MFC, some readers may wonder why I would recreate the same control without branching out into uncharted territory. But the fact of the matter is: I am indeed branching out, and this isn't simply a recreation.

I've never ventured into C# before. So rather than jump the gun and start out with an ambitious project that is nothing but of a stranger to me, I have decided to stick with something I am both familiar and comfortable with: porting my C2DPushGraph control to C#. After porting the control and discovering C# wasn't much different than C++ in ideology, I quickly shifted my focus to improving the feature set and overall design of the control, all while conforming to general C# standards and ethics.

That being said (or rather typed), the basis of the control remains the same. So my previously written CodeProject article's introduction also applies here:

"In past programming experiences, I've often had a desire to display and monitor the rate or performance of some operation on a graph. Whether it be the rate of write operations or the number of content results extracted each second, I always thought a graph similar to the graphs found in Windows XP’s Task Manager (CTRL-Alt-Delete) performance and networking tabs would do the trick well. After a quick search on Google for the graph control clone yielded no relevant results, I decided cloning it myself would be an interesting and beneficial experience. As time progressed and cloning the control proved itself easy, I decided to add more features and make it completely customizable in nearly every aspect. In the end, as the smoke cleared, I was left face to face with the control this article revolves around. It looked and behaved astonishingly beautiful for being developed with such haste. But who cares about its pastime, let's move on and see how easy it is to implement..."

Using the Code

Adding the Control to your Windows Form

The easiest and simplest method of adding the C2PushGraph control to a Windows Form is by first adding it to your control toolbox in Visual Studio. To accomplish this, you can follow these steps in Visual Studio 2005:

  1. Download the control source
  2. Extract the control's DLL to your project directory
  3. Open your project
  4. Open Visual Studio's “Tools” menu item
  5. Click “Choose Toolbox Items”
  6. Click the Browse button
  7. Locate the C2PushGraph DLL, and click “Open”

After performing these steps, you'll be able to drag and drop the C2DPushGraph control into your form from the Toolbox (under Common Controls) just like any other standard control. To continue following along with the tutorial using this method, go ahead and drag the control to your form; then, name it m_PushGraph.

The alternate method of adding the control to your form involves manually coding the control instantiation and its creation within your form. While seldom used, this method proves itself useful if you want to add the control “on the fly”.

The first suggested step is including the CustomUIControls.Graphing namespace in the scope of your cs file. This is of course done by including “using CustomUIControls.Graphing” at the head of the file.

Next, you'll need to add a new C2DPushGraph variable to your form class (for the sake of this tutorial, we'll call it m_PushGraph). Now, in the method where you'd like to create the control, use one of the following code blocks as a guide to create and add the control to your form:

// This example creates the control and automatically


// adds it to the form ('this') with the positioning

// referenced in the passed Rectangle:


m_PushGraph = new C2DPushGraph( this, 
  new Rectangle( Xpos, Ypos, GraphWidth, GraphHeight ));


// This example simple creates the control

// and automatically add it to the form ('this'):


m_PushGraph = new C2DPushGraph( this );

// This example uses the standard manual


// method for adding a control:


m_PushGraph = new C2DPushGraph();
this.Controls.Add( m_PushGraph );

Setting the Graph Range

After instantiating the C2DPushGraph variable, you'll need to set your graph's range. A range consists of the highest and lowest magnitudes that you intend to push to a line. An example would be setting the range of a CPU usage graph from 0 to 100.

You set the range by setting 'MinPeekMagnitude' to the smallest numerical magnitude you may potentially push to a line within the graph. Inversely, 'MaxPeekMagnitude' specifies the maximum potential magnitude.

Note: If AutoAdjustPeek is set to true (by default it isn't), it is suggested that you only provide a 'rough range'. When this mode is enabled, the range is automatically adjusted to contain any magnitude.

Adding a New Line

Now that we have our basic graph all ready to roll, we'll want to add one or more new lines to it. But before we dive any deeper into the conventions of calling this method, it's important to understand how lines are identified.

A line can either be uniquely identified using a numerical ID (slightly better performance) or by using a name (more convenient). This identification provides us with a way to obtain references to lines at anytime without having to keep track of the line handles. It is important to note that the choice of using IDs or just obtaining and storing the line handle after line creation is a matter of personal preference (you could even use a combination of both).

To add a new line, we call the control's conveniently named 'AddLine' method, which in turn creates and adds a line to our graph, and then returns the line handle. 'AddLine' requires two parameters: the desired numerical ID or name for future reference, and the line's initial color. If the line is successfully added to the graph, the line's 'C2DPushGraph.LineHandle' reference will be returned. If the passed numerical ID or name is not unique, a null value will be returned:

// This example uses a numerical ID for our line:


const int EXAMPLE_LINE = 47;
MyLineHandle = m_PushGraph.AddLine( EXAMPLE_LINE, Colors.Blue ); 

if (MyLineHandle == null)
{
    // ... Line already exists.

}

// This example uses a name for our line:


MyLineHandle = m_PushGraph.AddLine( "My Example Line", Colors.Blue ); 

if (MyLineHandle == null)
{
    // ... Line already exists.

}

Pushing a New Magnitude Point to your Line

Pushing a new point to our newly created line is anything but non-trivial. The first thing to do, is to call the control's 'Push' method, and pass the line's ID or name, in addition to the magnitude you'd like to plot. If your graph contains more than one line, you should perform the same process for all the other lines displayed on the graph before continuing. An example of this process follows below:

const int EXAMPLE_LINE = 47; // Used in our last example


// Push a magnitude of 20 to our numerically identified line:

m_PushGraph.Push( EXAMPLE_LINE, 20 );

// Push a magnitude of 76 to our named line:

m_PushGraph.Push( "My Example Line", 76 );


// Update the graph (explained in next section):

m_PushGraph.UpdateGraph();

Updating the Graph

With our graph fundamentally established and our first set of magnitudes pleasantly awaiting their visual debut, our last required step is to update and redraw our C2DPushGraph control. If you look back to the previous code example, you'll likely (and hopefully) notice it introduced a new unexplained method: “UpdateGraph”.

Luckily, UpdateGraph's written explanation can be short due to its simplistic nature. It does exactly as the name implies; it updates our graph control to take any newly pushed magnitudes or lines into account when rendering the control (which it also does). Optimally, you should only call “UpdateGraph” after pushing an equal number of magnitudes to each line included in your graph; but such methodology is not required (see Additional Notes).

Customizing the Appearance and Behavior of your Graph

Although our graph is now incorporated and completely functional within our application (assuming you've been referring to this tutorial as a general guide to implementing the control), we still have a great deal of features to explore. All of these features involve properties to adjust aesthetics and behavior. While altering them is purely optional, they'll provide greater depth and visual splendor to your application.

To provide you with a mental representation of the general graph components, refer to the following image:

Additional Properties

  • AutoAdjustPeek

    Type: bool

    Gets or sets a boolean value indicating whether the graph automatically adjusts its range to include any magnitude pushed to its lines (auto scaling).

  • BackColor

    Type: Color

    Gets or sets the background color of the graph.

  • BackgroundImage

    Type: Image

    Gets or sets the background image to be used for the graph (overrides the background color).

  • GridColor

    Type: Color

    Gets or sets the graph's grid color.

  • GridSize

    Type: ushort

    Gets or sets the width/height (in pixels) of each square in the graph's grid.

  • HighQuality

    Type: bool

    Gets or sets a boolean value indicating whether the graph is rendered in 'high quality' mode (with antialiasing). It is suggested that this property be set to false if you intend to display your lines using bar graph styles, thickness greater than two, or if maximum performance is absolutely crucial.

  • LineInterval

    Type: ushort

    Gets or sets the number of pixels between each displayed magnitude.

  • MaxLabel

    Type: String

    Gets or sets the string to display as the graph's 'maximum label'.

  • MinLabel

    Type: String

    Gets or sets the string to display as the graph's 'minimum label'.

  • ShowGrid

    Type: bool

    Gets or sets a boolean value indicating whether the graph's grid is to be displayed.

  • ShowLabels

    Type: bool

    Gets or sets a boolean value indicating whether the minimum and maximum labels are to be displayed.

  • TextColor

    Type: Color

    Gets or sets the color of the labels displayed in the graph (labels).

Customizing the appearance of your lines

The appearance of individual lines can be altered by changing properties using the line's handle. If you have not retained handles for each of your lines, they can be retrieved by calling “GetLineHandle” and passing each subsequent line's numerical ID or name as the only parameter. Once you have the line handle, you may access the handle's following public properties:

Properties:

  • Color

    Type: Color

    Sets or gets the line's current color.

  • ShowAsBar

    Type: bool

    Gets or sets a boolean value indicating whether this line's magnitudes are displayed in a bar graph style.

  • Thickness

    Type: uint

    Sets or gets the line's thickness in pixels. Note: It is advisable to set your control's HighQuality property to false if using a thickness greater than two pixels, as the antialiasing creates imperfections.

  • Visible

    Type: bool

    Gets or sets a boolean value indicating whether the line is visible.

Additional Notes

  • This graph control does not automatically update itself at regular intervals; it is up to the developer to produce such functionality through timers or other techniques.
  • To remove a line, call the control's 'RemoveLine' method with either the line's numerical ID or name as the only parameter. If the line is successfully removed, the return value will be 'true'.
  • To check if a line exists, call the control's 'LineExists' method with either the line's numerical ID or name as the only parameter. If the line exists, the return value will be 'true'.
  • You can clear a line's magnitudes by calling the line handle's 'Clear' method.
  • It is suggested that you disable 'High Quality' if using one or more line(s) with a thickness greater than two pixels due to imperfections caused by antialiasing.
  • Although frowned upon, it is possible to push magnitudes to lines unequally (i.e.: two to one line, one to another line) prior to updating the graph. The graph automatically compensates and displays the lines without interruption.
  • The only reason this class is named C2DPushGraph (using a Hungarian derivative) instead of 2DPushGraph, is due to the inability to name classes using a leading numeral.

Contacting the Author

If you have any questions or comments regarding this control, please feel free to send Stuart Konen an e-mail at skonen@gmail.com.

Stuart Konen can also be contacted via AOL's Instant Messenger: Screen name 'Griblik3'.

History

  • November 28th, 2006 - Began work on C2DPushGraph.
  • December 2nd, 2006 - Submitted C2DPushGraph to The Code Project.
  • January 14th, 2008 - Added fix for potential hang with locked workstations.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Stuart Konen
United States United States
Member
Well first of all, it is fairly obvious my name is Stuart Konen (I'm sure 50% of you just took notice), all of my life I've lived on a farm located in Northern Idaho. What shatters the stereotype of rural residence however, is the fact that I'm very active in the technology and programming worlds. I took up the hobby of programming at age 9, at that point it was little language known as Quick Basic *sigh*. Fast forward another 9 years... (Woah... I just realized that's half of my existence. But that's something I'll have to contemplate later, as I have an autobiography to tell).
 
Now my experience in programming has improved vastly, I've released various technologies and programs and I'm continuing to pump out concepts and systems that are getting glances from all over the world. My weapon of choice is C++, the core language of the majority of freshly released software, it's sleak, mean, and incrediably powerful. On the side I venture into web application development and site design, where my interest lies in PHP. Over the years my project have included everything from Artificial Intelligence to Web Statistic Tracking systems, but that's the past. What matters is the future... Remember that question we were always asked in grade school? Where did we see ourselves in 10 years. Well that question was asked about 8 years ago in my life, so it looks as though I only have two more for planning stages. In two years I see myself plunging into the world of research, creating my own Research and Development firm, aiming to meet the never-ending need for new and superior software and technology. Soon after becoming a multi-billionare I'll pursue my dream of world domination. Nobody is perfect...
 
Actually when it comes down to things, the money has no meaning. But there you have it, a 5 minute slice of my thoughts and time... If you have any job opportunities or have the slight urge to initiate a conversation with me, it can be done via email: skonen [at] gmail [dot] com

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralGreat workmemberhjgode6 Dec '12 - 18:07 
Hello
 
thanks for this great contribution. This is exactly what I need for my Windows Mobile remote CPU monitor. I already tried MSChart control, but this is a overload for what I need.
 
I love the easy of use and your clean, understandable article.
 
regards from germany
 
Josef
GeneralMy vote of 5memberAbuman1 Jan '12 - 1:16 
Great work and helpful. But the tutorial has some bugs Smile | :) . For example m_PushGraph.Push( "My Example Line", 76 ); has the parameter interchanged.
Thanks for sharing
GeneralMy vote of 5membertusharpal9 Mar '11 - 0:01 
Thanks for sharing
GeneralMy vote of 5memberhoernchenmeister9 Feb '11 - 1:33 
Exactly what I was looking for... still very usefull in 2011
GeneralClearing the graphmemberMember 475451617 Dec '08 - 0:07 
Hi, How can i clear the graph from all displayed lines? i actualy whant to Init it to next display.
Thanks,
GeneralLabeling featurememberkirant4009 Nov '08 - 18:16 
Hi,
 
Too good control. But i want to have labels for the x-axis points. How can i do that with this control? I tried but i m not able to get any...
 
Please help.
Also is there an option to watch the previous values, Like scroll-bar or so?
GeneralRe: Labeling featurememberE. del Ayre9 Nov '08 - 21:11 
kirant400 wrote:
I tried but i m not able to get any...

 
yeah, you can... i did so like...
		g.DrawString(m_szBottomMidLabel, Font, Brushes.Yellow,
			(float)((Width - m_OffsetX) / 2 + m_OffsetX - (nBottomMidLabelWidth / 2)), 
			(float)(Height - nBottomMidLabelHeight) );
use the OnPaint e.Graphics (g) and call DrawString(...)
dont worry about the last 2 param, they are just for positioning...
 
kirant400 wrote:
Also is there an option to watch the previous values

 
this will take some work... make a List of coordinates ( - the actual values in the Push function )... and some screen position conversions... Dead | X| ...
 
think fast, be brave and dont stop.

QuestionBug?: minimize graph, while minimized add a line, wait a little and restore the windows: no lines after thatmemberparmando23 Sep '08 - 13:20 
Hello,
 
I think there is a bug somewhere in the control. I use a timer to gather some values to represent.

I start the application, start the timer, I see the lines in the graph, then I minimize the window, (the timer continues its work), after a minute I restore the window and the control show no line and start drawing at the very left side of the control as if never before a value was pushed into it. Do you have any idea of what can be happen here?
QuestionI want "Visible" functionmemberqToTpz7 Jul '08 - 19:49 
how can I? T.TConfused | :confused:
GeneralCongratulations!memberVenomVTS10 Jun '08 - 20:01 
Man, this is the best TaskManager-like graph control I have EVER seen! Besides it's functionality, it's all in one class. Really GREAT JOB! Thanks alot for sharing it!
QuestionSir...memberti-oh4 Feb '08 - 16:24 
Before anything else, Id like to say you did a great job on this control...
I like it's simple and direct to the point functionality... Behind it, is a clean and quality implementation...
 
Im very much looking forward to incorporating this control class to one of the projects im handling right now... It would be a great help since the company didnt opt to buy additional charting license... (for a mere utility program)
 
The project is using C++ (2005), and for that, im asking your permission since I'll be converting your codes into .h and .cpp... I know, I could just reference the existing assembly/dll... But, knowing my boss he wouldnt want many dlls running around... (so, a class will do)
 
Ofcourse, Ill make sure both credits & comments remain while converting between languages... And ensure to you the terms and conditions bound by CPOL...
 
So, its a yes, right?
 
think fast, be brave and dont stop.

GeneralRe: Sir...memberStuart Konen8 Feb '08 - 18:48 
Thank you for the positive feedback... Feel free to convert it to whatever language you need. You can do whatever you wish with this control.
Questionneed help on bargraphmemberPedrinha7 Jan '08 - 16:55 
hi.. does anyone know how to create a horizontal bargraph with all the labels at e axis? it needs to be connected to a database (sql).. using visual basics.. anyone has the code?
 
really need your help asap.. thx alot.. Big Grin | :-D
GeneralExcellent CodememberShalomZ9 Aug '07 - 12:33 
Big Grin | :-D
Thank you very much for sharing your code with us. It is a wonderful graph control.Big Grin | :-D
QuestionFeatures ?membercdemez7 May '07 - 22:31 
Hi,
 
It will be fine to have a ScrollBar option to allow scrolling (horizontal and vertical) to see previous values.
 
Also, it will be fine too to be able to zoom.
 
Thanks
 
Krys

Questionbug after a long workstation lockmemberFabrice Deshayes aka Xtream30 Mar '07 - 2:06 
Hi!
 
i've used your graph component to display CPU/RAM/LAN/WAN infos lineq on my application but i've got a probleme. If i lock my workstation for the night, when i unlock it on the next morning, my application freeze, my CPU is at 100% and it can stay like this for a while (10 minute).
 
If i remove you graph components and replace it but a homemade VUMETER, the problem disappear. Any idea about what's happen ?
GeneralRe: bug after a long workstation lockmemberStuart Konen30 Mar '07 - 4:42 
I think the first thing that needs to be done here is verify that the problem lies within the control. If you lock your workstation while the provided C2DPushGraph demo is running, will the same problem occur in the morning? Just make sure when you check, you don't have both the demo and your app with the C2DPushGraph running overnight at the same time, otherwise it won't be discernible as to which is causing the problem.
 
I've tried doing the same on my machine, and everything went smoothly. What operating system are you using? And what all occurs during a lockdown?
GeneralRe: bug after a long workstation lockmemberFabrice Deshayes aka Xtream10 Apr '07 - 22:23 
hi! i've done the same thing with the C2DPushGraph example and i've got the same probleme. I've lock my workstation for the night and in the morning, the C2D example was "freeze". 100% cpu used and no GUI refresh. I've done a screenshot if you want. This probleme has occured on 2 differents PC with Win XP SP2 (1 go of ram, athlon or ahtlon 64 processor, fresh installed XP)
GeneralRe: bug after a long workstation lockmemberStuart Konen8 May '07 - 6:13 
Anash Oommen has pointed out a fix for this, and the updated version should be available very soon.
GeneralRe: bug after a long workstation lockmemberFabrice Deshayes aka Xtream8 May '07 - 7:47 
thanks! i'll checked it every day until next released.
GeneralRe: bug after a long workstation lock [modified]memberFabrice Deshayes aka Xtream1 Jun '07 - 23:22 
some news about the updated version ??
 

-- modified at 13:04 Sunday 1st July, 2007
GeneralWell donemembernausea00120 Feb '07 - 21:54 
Excellent code, good job.
GeneralThanks a lot!memberMember #124954619 Feb '07 - 3:06 
Most helpful.
 
Ofer
GeneralTwo graphs on the same Windows formmemberalbyd7417 Dec '06 - 8:54 
Is it possible to add two graphs on the same Form?
I tried, but the second one appears with a big red cross on it... Confused | :confused:
Thanks
GeneralYour codememberStuart Konen17 Dec '06 - 11:07 
Post the code you are using to initialize the graph's. There should not be any conflict between multiple graphs, so the problem must be in relation to your code.

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

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 15 Jan 2008
Article Copyright 2006 by Stuart Konen
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid