Article Options
Premium Sponsor
Premium Sponsor

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

Ged Mead (XTab) has been around computers since the 1980's when the first affordable home computers came on the market. His journey from that very first Dragon 32 to the present has taken him through many different facets of the IT Industry. These include formal training as a Systems Analyst, employment in a mainframe software development environment, and a short time spent demonstrating rugged military IT systems in the days when it took two strong men to carry a 'mobile' system.

His most rewarding challenge was the creation of a financial management system for a large organisation.

Now based in an idyllic lochside location in the West of Scotland, he is currently involved in a range of development projects, whenever he can drag his gaze away from the stunning surrounding views, that is!

Ged is a Microsoft MVP, Senior Editor for DevCity.NET, vbCity Developer Community Leader and Admin, Helper of the Month competition winner and DevCity.NET newsletter Editor.

 

View all articles by Ged Mead...
Introduction

   There are some quite advanced features that can be incorporated into a dynamic chart, sometimes depending on where the data is coming from.   In this article, we are going to be begin with a fairly simple demo.   Then we will move on to one that is slightly more sophisticated and finally we will look at further enhancements that could be incorporated into this kind of graph.

   So, let me set the scene.  What do we want to do here?   Well, the first dynamic line chart I plan to create is one that takes some simple user input and displays the values as they are chosen on the chart.   As each new value is selected, the chart will be extended and redrawn to show the continuous changes that have been made.  When the screen width is "full", the earliest values are lost from view as the graphic display continues to scroll from right to left.

  One quick and easy demo is to create put a scrollbar on a form and use the changing scrollbar values as the data for the chart.   Take a look at the sample form below.

 

Form Controls    

    The silver grey area is a PictureBox.  As the values in the ScrollBar change, so the graph represents the new values.  I have used a Vertical ScrollBar here, but you can just as easily use a Horizontal ScrollBar.  In either event, the coding logic will be the same.

   Here are the steps to create the form.  

  1. Add a ScrollBar control to the form.  Set its Minimum property to 0, its Maximum to 104.  (If you are wondering why I've picked that Maximum value, see the note at the bottom this page) .  Set the LargeChange property to 5; leave the SmallChange property as 1.  Change the control's name to SBUserValue to reflect its purpose - scroll bar to detect user's chosen values.
  2. Add a PictureBox and name it picGraph.   Set its height to exactly 400.   Why ?   This is really just a way of keeping the scaling code as easy as possible.   The user values are going to be numbers between 0 and 100, so it will be very easy to multiply the value by 4 to automatically scale it vertically on the picturebox graph.     Real life almost certainly won't be this easy, but it will help us concentrate on the important drawing stuff for this first demonstration.  Change the PictureBox'sname to picGraph and set its backcolor to Gainsborough (or any other color that you prefer)
  3. Finally,add a label to display the changing selection value.  This label plays no part in the chart creation; I've included it so you can check that any given value is correctly represented on the chart itself.   Name it lblValue.
  4. The remaining label controls shown on the screenshot above are entirely optional and are not referred to in any of the code that follows.

   Initial Code

   Place this Imports statement at the top of the form:

 Imports

System.Drawing.Drawing2D

    As you will know if you have read the earlier articles in this series, this allows us to use any of the  Drawing.Drawing2D class methods and properties in code without having to keep writing out the fully qualified names each time.  

   In the next step we will build the code that does all the drawing in the chart, dynamically changing the display each time a new value is selected via the ScrollBar.

----------------------------------------------------------------------------------------------------------------

   Note:

     The reason for setting a Maximum value of 104 (when what we really want is 0 to 100 on the scale) is due to what seems to me to be a small foible with the ScrollBar control.     If you set the Maximum to 100 and the Large Change to 5 then the highest value you will be able to physically obtain by moving the slider or clicking on the ScrollBar's arrow will be 96.  There may be an official fix for this, but I find that offsetting the Maximum by a figure of (LargeChange - 1) seems to do the trick.

  

 

     

   

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!
 
Sponsored Links