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..."
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:
C2PushGraph
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.
C2DPushGraph
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.
CustomUIControls.Graphing
using CustomUIControls.Graphing
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 );
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.
MinPeekMagnitude
MaxPeekMagnitude
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.
AutoAdjustPeek
true
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:
AddLine
C2DPushGraph.LineHandle
// 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 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:
Push
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();
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”.
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).
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:
Type: bool
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
Color
Gets or sets the background color of the graph.
BackgroundImage
Type: Image
Image
Gets or sets the background image to be used for the graph (overrides the background color).
GridColor
Gets or sets the graph's grid color.
GridSize
Type: ushort
ushort
Gets or sets the width/height (in pixels) of each square in the graph's grid.
HighQuality
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.
false
LineInterval
Gets or sets the number of pixels between each displayed magnitude.
MaxLabel
Type: String
String
Gets or sets the string to display as the graph's 'maximum label'.
MinLabel
Gets or sets the string to display as the graph's 'minimum label'.
ShowGrid
Gets or sets a boolean value indicating whether the graph's grid is to be displayed.
ShowLabels
Gets or sets a boolean value indicating whether the minimum and maximum labels are to be displayed.
TextColor
Gets or sets the color of the labels displayed in the graph (labels).
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:
GetLineHandle
Type: Color
Sets or gets the line's current color.
ShowAsBar
Gets or sets a boolean value indicating whether this line's magnitudes are displayed in a bar graph style.
Thickness
Type: uint
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
Gets or sets a boolean value indicating whether the line is visible.
RemoveLine
LineExists
Clear
2DPushGraph
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'.
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)
kirant400 wrote: I tried but i m not able to get any...
g.DrawString(m_szBottomMidLabel, Font, Brushes.Yellow,
(float)((Width - m_OffsetX) / 2 + m_OffsetX - (nBottomMidLabelWidth / 2)),
(float)(Height - nBottomMidLabelHeight) );
kirant400 wrote:Also is there an option to watch the previous values
General News Suggestion Question Bug Answer Joke Praise Rant Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.