Click here to Skip to main content
15,881,715 members
Articles / Multimedia / GDI+
Article

C2DPushGraph: A Push Graph Control

Rate me:
Please Sign up or sign in to vote.
4.74/5 (36 votes)
15 Jan 2008CPOL9 min read 129.2K   6.7K   134   32
A push graph control similiar to the graph control located in Microsoft's Task Manager.

Image 1

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:

C#
// 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:

C#
// 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:

C#
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:

Image 2

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)


Written By
United States United States
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

Comments and Discussions

 
Questionoscilloscope runtime graph Pin
Member 1286844228-Dec-16 0:07
Member 1286844228-Dec-16 0:07 
Questionoscilloscope runtime graph Pin
Member 1286844214-Dec-16 20:19
Member 1286844214-Dec-16 20:19 
GeneralGreat work Pin
hjgode6-Dec-12 18:07
hjgode6-Dec-12 18:07 
GeneralMy vote of 5 Pin
Abuman1-Jan-12 1:16
Abuman1-Jan-12 1:16 
GeneralMy vote of 5 Pin
_Tushar Patil9-Mar-11 0:01
_Tushar Patil9-Mar-11 0:01 
GeneralMy vote of 5 Pin
hoernchenmeister9-Feb-11 1:33
hoernchenmeister9-Feb-11 1:33 
GeneralClearing the graph Pin
ron barzilai17-Dec-08 0:07
ron barzilai17-Dec-08 0:07 
GeneralLabeling feature Pin
kirant4009-Nov-08 18:16
kirant4009-Nov-08 18:16 
GeneralRe: Labeling feature Pin
E. del Ayre9-Nov-08 21:11
E. del Ayre9-Nov-08 21:11 
QuestionBug?: minimize graph, while minimized add a line, wait a little and restore the windows: no lines after that Pin
parmando23-Sep-08 13:20
parmando23-Sep-08 13:20 
QuestionI want "Visible" function Pin
qToTpz7-Jul-08 19:49
qToTpz7-Jul-08 19:49 
GeneralCongratulations! Pin
VenomVTS10-Jun-08 20:01
VenomVTS10-Jun-08 20:01 
QuestionSir... Pin
E. del Ayre4-Feb-08 16:24
E. del Ayre4-Feb-08 16:24 
GeneralRe: Sir... Pin
Stuart Konen8-Feb-08 18:48
Stuart Konen8-Feb-08 18:48 
Questionneed help on bargraph Pin
Pedrinha7-Jan-08 16:55
Pedrinha7-Jan-08 16:55 
GeneralExcellent Code Pin
S Keller9-Aug-07 12:33
S Keller9-Aug-07 12:33 
QuestionFeatures ? Pin
cdemez7-May-07 22:31
cdemez7-May-07 22:31 
Questionbug after a long workstation lock Pin
Fabrice Deshayes aka Xtream30-Mar-07 2:06
Fabrice Deshayes aka Xtream30-Mar-07 2:06 
GeneralRe: bug after a long workstation lock Pin
Stuart Konen30-Mar-07 4:42
Stuart Konen30-Mar-07 4:42 
GeneralRe: bug after a long workstation lock Pin
Fabrice Deshayes aka Xtream10-Apr-07 22:23
Fabrice Deshayes aka Xtream10-Apr-07 22:23 
GeneralRe: bug after a long workstation lock Pin
Stuart Konen8-May-07 6:13
Stuart Konen8-May-07 6:13 
GeneralRe: bug after a long workstation lock Pin
Fabrice Deshayes aka Xtream8-May-07 7:47
Fabrice Deshayes aka Xtream8-May-07 7:47 
GeneralRe: bug after a long workstation lock [modified] Pin
Fabrice Deshayes aka Xtream1-Jun-07 23:22
Fabrice Deshayes aka Xtream1-Jun-07 23:22 
GeneralWell done Pin
nausea00120-Feb-07 21:54
nausea00120-Feb-07 21:54 
GeneralThanks a lot! Pin
Member 124954619-Feb-07 3:06
Member 124954619-Feb-07 3:06 

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

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