Article Options
Recently Viewed
Premium Sponsor
Premium Sponsor

 »  Home  »  .NET Newbie  »  GDI+ Chart Success Part 6: Dynamic Line Chart  »  A More Generic Version
 »  Home  »  Windows Development  »  Graphics  »  GDI+ Chart Success Part 6: Dynamic Line Chart  »  A More Generic Version
 »  Home  »  Windows Development  »  Win Forms  »  GDI+ Chart Success Part 6: Dynamic Line Chart  »  A More Generic Version
GDI+ Chart Success Part 6: Dynamic Line Chart
by Ged Mead | Published  08/22/2006 | .NET Newbie Graphics Win Forms | Rating:
A More Generic Version

Versatile Guidelines
We have made life relatively easy for ourselves so far by keeping to predefined and easy-to-use values in the demonstrations. While this is fine for the purposes of this article, I'm sure you will want to know how you can translate the logic in a way that allows you to create these kinds of charts for other ranges of values and other sizes of display.


That's what we will look at now.

Display Guidelines
Instead of using a procedure which has the values hard coded into it, we will move on to one that takes parameters. We change from a Sub to a Function as this allows us to pass in the parameters needed and to receive in return a newly minted Bitmap object.

Here is the replacement Function:

Private Function DisplayGuidelines(ByVal PicBox As PictureBox, ByVal chunks As Integer) As Bitmap
' Step 1
' Create a bitmap to draw on and grab its Graphics Object
Dim bm As New Bitmap(PicBox.Width, PicBox.Height)
Dim gr As Graphics = Graphics.FromImage(bm)

' Step 2
' Draw guidelines on main chart.
' Get the total height available and split it into chunks
Dim total As Integer = PicBox.Height
Dim chunk As Single = total / chunks

' Step 3
For i As Single = chunk To total Step chunk
gr.DrawLine(Pens.WhiteSmoke, 0, i, PicBox.Width, i)
Next i

' Step 4
' return the results.
Return bm

' Step 5
gr.Dispose()
End Function

Let's take a look at the key changes.

Step 2 calculates the vertical space between each line. This is simply done by dividing the total height of the PictureBox by the number of lines (chunks) requested.

Step 3 is a generic version of the original loop that draws the lines; the values no longer hard coded.
Although I have used the Pens.WhiteSmoke Pen in the procedure, you could of course add a third parameter to it and allow the client code to set a pen color of choice.

Step 4 Returns a Bitmap object. This is slightly different to the original Sub, where we assigned the Bitmap to a PictureBox whose name was hard coded. In this replacement Function, we can assign the Bitmap in any way we like to any control that can use it.

We can call this function on Form_Load:

Private Sub _3rd_More_Generic_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
picGraph.Image = DisplayGuidelines(picGraph, 12)
End Sub

which in this example, creates 12 Guidelines and draws them on the PictureBox named picGraph

Guidelines and Plotted Values
In the same vein, let's now look at making the procedure that plots the values more widely usable.


Here's the replacement procedure - again it's now a Function, not a Sub.

Private Function DisplayGuidelinesAndChart(ByVal PicBox As PictureBox, ByVal chunks As Integer, _ ByVal XMove As Integer, ByVal NewValue As Single, ByVal Min As Single, ByVal Max As Single) As Bitmap

' Step 1
' Grab the current image (the latest version of the chart)
Dim bm As New Bitmap(PicBox.Width, PicBox.Height)
Dim gr As Graphics = Graphics.FromImage(bm)


' Step 2
' Get the total height available and split it into chunks

Dim total As Integer = PicBox.Height
Dim chunk As Single = total / chunks
' Tack missing guidelines to right hand side on the Graphics object.
For i As Single = chunk To total Step chunk
gr.DrawLine(Pens.WhiteSmoke, PicBox.Width - XMove, i, PicBox.Width, i)
Next i


' Step 3
' Draw this grabbed image, placing it XMove pixels to the left

If Not IsNothing(PicBox.Image) Then
gr.DrawImage(PicBox.Image, -XMove, 0)
End If


' Step 4
' Plot the new value.
' Calculate the scaling required to make full use of the height of
' the PictureBox

Dim ValueRange As Single = Max - Min
Dim vScale As Single = PicBox.Height / ValueRange

' Apply the scale to the current value
NewValue *= vScale

' Step 5
' Shift start point from top left to bottom left.

gr.TranslateTransform(0, picGraph.Height)

' Step 6
' Draw the next line segment on the Graphics object.
' If Min is > 0 then you need to shift the drawing down once again,
' this time to put the Min value on the horizontal axis
If Min > 0 Then gr.TranslateTransform(0, Min * vScale)

' Step 7
' Return the Bitmap .

Return bm

' Step 8
' All done
gr.Dispose()
End Function

We have extended the parameters further and now take in client values for XMove, NewValue, Min and Max. XMove and NewValue have the same role as in all the previous examples; passing them in as parameters just makes the procedure more generalised.
We used the 'chunks' integer in the previous function and its role is the same in this one.

In Step 3 I have added some code to catch an intermittent bug that caused me problems. It would throw a "Value cannot be null" Exception occasionally; the problem being centered on the PicBox.Image at Form_Load . I wasn't able to satisfactorily pin down the cause of this problem because of its intermittent nature. An alternative solution is to place the DrawImage method in a Try Catch block; this will handle the Exception without crashing the application, but I found that there was an unwanted delay before the new form appeared, so I prefer the IsNothing fix.

In Step 4, parameters Min and Max are also both new. These are introduced to give you the ability to use ranges of values where the minimum isn't hard coded or assumed to be zero. Similarly,the maximum can be any figure that is dictated by the datasource used. Having these two values as parameters allows the function to calculate the scaling needed to fit into the available height of the PictureBox.

Also in Step 4, we calculate an appropriate scaling based on the available height of the PictureBox and the Maximum range to be covered. In the earlier examples, you may remember that we hard coded this scale to 4:1. Now however, we have much more flexibility.

In Step 6, as should be clear from the commenting, we now need to shift the drawing so that the minimum value (whatever it happens to be) is placed exactly in line with the horizontal axis. The TranslateTransform method simply moves the startpoint of the drawing by the appropriate scaled amount.

Other than that, there isn't much new to take in.

The Vertical Values
Finally, we need to apply the same sort of thinking to the procedure that populates the picValues PictureBox with Guidelines and Numbers. Although the code below, with its variables in place of the previous hard coded values, looks more complex, the code logic is in fact exactly the same. The commenting and variable names hopefully will help you see how this version reflects the hard coded values version.

Private Function DisplayVerticalValues(ByVal PB As PictureBox, ByVal HowManyChunks As Single, _
ByVal MinValue As Single, ByVal MaxValue As Single) As Bitmap


' Step 1
Dim bmp As New Bitmap(PB.Width, PB.Height)
Dim gv As Graphics = Graphics.FromImage(bmp)


' Step 2
' Draw guidelines on values strip
' Get the total height available and split it into chunks
' This value represents a number of pixels

Dim TotalPixels As Integer = PB.Height
Dim SingleChunk As Single = TotalPixels / HowManyChunks

For i As Single = SingleChunk To TotalPixels Step SingleChunk
gv.DrawLine(Pens.WhiteSmoke, 0, i, PB.Width, i)
Next i


' Step 3
' Draw Numbers as Text, correctly spaced vertically
' Begin with the highest value allowed

Dim NextMarker As Integer = MaxValue
Dim ValueRange As Single = MaxValue - MinValue


' Draw the numbers, decrementing values proportionately each time through the loop
For i As Single = 0 To TotalPixels Step SingleChunk
gv.DrawString(CStr(NextMarker), New Font("Verdana", 8, FontStyle.Regular), Brushes.Black, 1, i)


NextMarker -= (ValueRange / HowManyChunks)
Next


' Step 4
Return bmp

' Step 5
gv.Dispose()

End Function

So there you have the various changes and improvements needed to make the original idea much more flexible.    You can now extend the general approach for whatever particular source of data suits your purposes.


 

Comments    Submit Comment

Comment #1  (Posted by Mark Prichard on 08/24/2006)
Rating
I appreciate this series very much. Within minutes of finding your articles I had adapted the ideas to work in my personal project, and had a working graph.Thanks for taking the time to create this series.
 
Comment #2  (Posted by Robert Gillespie on 09/05/2006)
Rating
This is great. From knowing nothing about graphs I can now do graphs. Only one question. How would you print the graph.
 
Comment #3  (Posted by Ged Mead on 09/19/2006)
Rating
It looks as though there's going to have to be a Part 7 after all :-} I will publish a follow up showing how to print graphs, hopefully some time in the next few weeks.
In the meantime, Robert, I will email you some outline guidance.
 
Comment #4  (Posted by an unknown user on 09/28/2006)
Rating
Excellent article.
 
Comment #5  (Posted by FERNANDO HOOD on 01/06/2007)
Rating
Excellent document however the function keeps failing at

If Not IsNothing(PicBox.Image) Then
gr.DrawImage(PicBox.Image, -XMove, 0)
End If

System.InvalidOperationException was unhandled
Message="Object is currently in use elsewhere."
Source="System.Drawing"
StackTrace:
at System.Drawing.Image.get_Width()
at System.Drawing.Image.get_Size()
at System.Windows.Forms.PictureBox.ImageRectangleFromSizeMode(PictureBoxSizeMode mode)
at System.Windows.Forms.PictureBox.get_ImageRectangle()
at System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe)
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(ApplicationContext context)
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
at MaxiCOM.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81
at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()





 
Comment #6  (Posted by an unknown user on 01/10/2007)
Rating
How do I deal with a situation where the data for the graph is handle brought in b a subroutine running on it own thread e.g the serial port?
 
Comment #7  (Posted by an unknown user on 01/27/2007)
Rating
One of the best articles I have seen on charting. Very focused and "to the point" descriptions. Concentrates on the task at hand than introducing unnecessary programming complexities.
 
Comment #8  (Posted by an unknown user on 11/28/2007)
Rating
Great series!
 
Comment #9  (Posted by an unknown user on 09/01/2008)
Rating
This is Great!
 
Comment #10  (Posted by an unknown user on 06/12/2009)
Rating
This article teach me lot of things;
.. It is mind Blowing
 
Comment #11  (Posted by on 10/11/2009)
Rating

 
Comment #12  (Posted by As a narcotic analgesic, Tramadol can be abused. on 11/07/2009)
Rating
plavix libido plavix libido plavix libido . plavix libido plavix libido . plavix libido plavix libido . plavix libido uk carisoprodol supplier uk carisoprodol supplier . uk carisoprodol supplier uk carisoprodol supplier . uk carisoprodol supplier uk carisoprodol supplier . uk carisoprodol supplier uk carisoprodol supplier uk carisoprodol supplier . generic ambien soft tab generic ambien soft tab generic ambien soft tab generic ambien soft tab generic ambien soft tab . generic ambien soft tab generic ambien soft tab generic ambien soft tab generic ambien soft tab generic ambien soft tab .
 
Comment #13  (Posted by an unknown user on 11/12/2009)
Rating
First class intro for novices!!
 
Comment #14  (Posted by water-soluble and they are renally excreted. on 11/25/2009)
Rating
The mission of the your site.: URLsWithNothing
 
Comment #15  (Posted by Dsfgrg on 11/27/2009)
Rating
The more you know about site: URLsWithURL
 
Comment #16  (Posted by Silvia on 02/18/2010)
Rating
b6KspU I am always excited to visit this blog in the evenings.Please churning hold the contents. It is very entertaining.
 
Comment #17  (Posted by Dave on 03/02/2010)
Rating
Excellent, this really helped me out and was really well explained...
 
Comment #18  (Posted by Dave on 03/02/2010)
Rating
Where can I find the rest of the series please?
 
Comment #19  (Posted by Dave on 03/02/2010)
Rating
Where can I find the rest of the series please?
 
Comment #20  (Posted by Raja on 05/08/2010)
Rating
Hi, where can i find the source code file attachment..
 
Comment #21  (Posted by Silvia on 09/22/2010)
Rating
I am always excited to visit this blog in the evenings.Please churning hold the contents. It is very entertaining.
 
Comment #22  (Posted by OEM software download on 09/23/2011)
Rating
IY2n62 See it for the first time!!...
 
Comment #23  (Posted by Download oem software on 09/29/2011)
Rating
f5zrly Yet, much is unclear. Could you describe in more details!...
 
Comment #24  (Posted by OEM software online on 10/28/2011)
Rating
1EW5oN Good day! I do not see the conditions of using the information. May I copy the text from here on my site if you leave a link to this page?!...
 
Comment #25  (Posted by OEM software download on 10/29/2011)
Rating
L4taoF Uh, well, explain me a please, I am not quite in the subject, how can it be?!...
 
Comment #26  (Posted by OEM software download on 11/05/2011)
Rating
j6m42O Author, keep doing in the same way..!!
 
Comment #27  (Posted by Buy software on 11/05/2011)
Rating
W1ooml The Author is crazy..!!
 
Comment #28  (Posted by Buy OEM software online on 11/06/2011)
Rating
EkMIAP Received the letter. I agree to exchange the articles..
 
Comment #29  (Posted by Buy OEM software online on 11/09/2011)
Rating
bPDvcL Good! Wish everybody wrote so:DD
 
Comment #30  (Posted by Buy cheap Microsoft Office software online on 12/27/2011)
Rating
R7jaTU Sometimes I also see something like this, but earlier I didn`t pay much attention to this!....
 
Comment #31  (Posted by Buy cheap software online on 12/27/2011)
Rating
rwi0w4 Yeah, it is clear now !... Just can not figure out how often do you update your blog?!....
 
Comment #32  (Posted by Cheap oem software on 12/27/2011)
Rating
VmvnJu It`s really useful! Looking through the Internet you can mostly observe watered down information, something like bla bla bla, but not here to my deep surprise. It makes me happy..!!
 
Comment #33  (Posted by microsoft OEM software online on 12/27/2011)
Rating
JAyA5Z Informative, but not convincing. Something is missing but what I can not understand. But I will say frankly: bright and benevolent thoughts!....
 
Comment #34  (Posted by Microsoft Office oem software on 12/27/2011)
Rating
Z2TtA3 I would add something else, of course, but in fact almost everything is mentioned!....
 
Comment #35  (Posted by buy discount oem software on 01/11/2012)
Rating
M9Ra4g comment1
 
Comment #36  (Posted by oem software on 01/11/2012)
Rating
zUPqvC comment1
 
Comment #37  (Posted by discount oem software on 01/11/2012)
Rating
LAu1H7 comment4
 
Comment #38  (Posted by cheap oem software on 01/11/2012)
Rating
o1GK67 comment2
 
Comment #39  (Posted by cheap oem software on 01/11/2012)
Rating
FLZD9Z comment4
 
Comment #40  (Posted by buy oem software online on 01/13/2012)
Rating
gZv33C comment4
 
Comment #41  (Posted by cheap oem software on 01/13/2012)
Rating
4ugZv3 comment6
 
Comment #42  (Posted by oem software on 01/13/2012)
Rating
siGE9X comment4
 
Comment #43  (Posted by oem software online on 01/13/2012)
Rating
9fzFId comment2
 
Comment #44  (Posted by discount oem software on 01/13/2012)
Rating
6H06k2 comment2
 
Sponsored Links