none
Draw line on the chart area RRS feed

  • Question

  • Hi

    I try Draw a line on the chart area with this code :

    Public Class Form1
        Dim Dpoint1 As Point
        Dim Dpoint2 As Point
        Private Sub Chart1_MouseDown(sender As Object, e As MouseEventArgs) Handles Chart1.MouseDown
            Dpoint1.X = e.X
            Dpoint1.Y = e.Y
        End Sub
        Private Sub Chart1_MouseUp(sender As Object, e As MouseEventArgs) Handles Chart1.MouseUp
            Dpoint2.X = e.X
            Dpoint2.Y = e.X
            Dim myPen As Pen = New Pen(Brushes.Red, 1)
            Dim myGraphics As Graphics = Me.CreateGraphics
            myGraphics.DrawLine(myPen, Dpoint1, Dpoint2)
        End Sub
    End Class

    But the line plot outside of the chart area !!!  I want to draw the line on the chart area .

    And when change this code

     Dim myGraphics As Graphics = Me.CreateGraphics 

    to the 

     Me.Chart1.CreateGraphics 

    Line is not drawn correctly ! 

    Anyone can help


    • Edited by ali-IRAN Friday, April 29, 2016 11:33 AM
    Friday, April 29, 2016 11:28 AM

Answers

  • This code will allow the mouse to draw a line within a ChartArea using a HitTest. The logic for the Mouse Events could probably be better though. I forgot to add logic if you mouse down within a ChartArea and MouseUp outside a ChartArea though which will probably leave the silver line on the Chart until you move the mouse back into the Chart area and mouse down and mouse up or something.

    I've also never had two chart areas where one is on one area of the Chart and the other has different x and y axis minimum and maximums so I didn't think about that when I did the logic. But you should be able to alter the logic using the HitTest logic in case you move the mouse out of one chart area while holding the left button down into another chart area.

    First place the cursor on the Chart and select left mouse button and hold it down, move the mouse to wherever you want to draw a line from and to and while moving the mouse a 1 pixel width silver line will appear following the mouse cursors point from the original starting point. When you get to where the end of the line should be then let the left mouse button up and the line will be drawn in 3 pixel width red line from starting point to end point.

    Next time mouse left button goes down in ChartArea it clears the line. The next mouse left button down in the ChartArea starts the process over.

    The pictures 2nd and 3rd images don't match with regard to the silver lines start point cause I was taking screenshots and had to start over for the 3rd image so the start point differs from the 2nd image.

    Option Strict On
    
    Imports System.Windows.Forms.DataVisualization.Charting
    
    Public Class Form1
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.Location = New Point(CInt((Screen.PrimaryScreen.WorkingArea.Width / 2) - (Me.Width / 2)), CInt((Screen.PrimaryScreen.WorkingArea.Height / 2) - (Me.Height / 2)))
            Chart1.Series.Clear()
            Chart1.ChartAreas.Clear()
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            IsMouseDown = False
            IsMouseMoving = False
            IsMouseUp = False
            RemoveHandler Chart1.MouseDown, AddressOf Chart1_MouseDown
            RemoveHandler Chart1.MouseMove, AddressOf Chart1_MouseMove
            RemoveHandler Chart1.MouseUp, AddressOf Chart1_MouseUp
            RemoveHandler Chart1.Paint, AddressOf Chart1_Paint
            Chart1.Series.Clear()
            Chart1.ChartAreas.Clear()
            Chart1.ChartAreas.Add("ChartArea1")
            Chart1.ChartAreas("ChartArea1").AxisX.Minimum = 0
            Chart1.ChartAreas("ChartArea1").AxisX.Maximum = 100
            Chart1.ChartAreas("ChartArea1").AxisX.Interval = 10
            Chart1.ChartAreas("ChartArea1").AxisY.Minimum = 0
            Chart1.ChartAreas("ChartArea1").AxisY.Maximum = 100
            Chart1.ChartAreas("ChartArea1").AxisY.Interval = 10
            Chart1.Series.Add("Test")
            Chart1.Series("Test").ChartType = SeriesChartType.Line
            Chart1.Series("Test").Color = Color.Lime
            Chart1.Series("Test").BorderWidth = 5 ' Set the lines width
            Chart1.Series("Test").MarkerColor = Color.Magenta
            Chart1.Series("Test").MarkerBorderColor = Color.Black
            Chart1.Series("Test").MarkerBorderWidth = 1
            Chart1.Series("Test").MarkerSize = 12
            Chart1.Series("Test").MarkerStyle = MarkerStyle.Star10
            Chart1.Series("Test").Points.AddXY(10, 10)
            Chart1.Series("Test").Points.AddXY(90, 90)
    
            AddHandler Chart1.MouseDown, AddressOf Chart1_MouseDown
            AddHandler Chart1.MouseMove, AddressOf Chart1_MouseMove
            AddHandler Chart1.MouseUp, AddressOf Chart1_MouseUp
            AddHandler Chart1.Paint, AddressOf Chart1_Paint
        End Sub
    
        Dim DownPoint As Point
        Dim IsMouseDown As Boolean = False
        Dim MovingPoint As Point
        Dim IsMouseMoving As Boolean = False
        Dim UpPoint As Point
        Dim IsMouseUp As Boolean = False
        
    
        Private Sub Chart1_MouseDown(sender As Object, e As MouseEventArgs)
            Dim ChartHitTest As HitTestResult = Chart1.HitTest(e.X, e.Y)
            If ChartHitTest.ChartArea Is Chart1.ChartAreas("ChartArea1") Then
                If IsMouseDown = False And IsMouseUp = False Then
                    DownPoint = New Point(e.X, e.Y)
                    IsMouseDown = True
                Else
                    IsMouseUp = False
                    Chart1.Refresh()
                End If
            End If
        End Sub
    
        Private Sub Chart1_MouseMove(sender As Object, e As MouseEventArgs)
            Dim ChartHitTest As HitTestResult = Chart1.HitTest(e.X, e.Y)
            If ChartHitTest.ChartArea Is Chart1.ChartAreas("ChartArea1") Then
                If IsMouseDown = True Then
                    IsMouseMoving = True
                    MovingPoint = New Point(e.X, e.Y)
                    Chart1.Refresh()
                End If
            End If
        End Sub
    
        Private Sub Chart1_MouseUp(sender As Object, e As MouseEventArgs)
            Dim ChartHitTest As HitTestResult = Chart1.HitTest(e.X, e.Y)
            If ChartHitTest.ChartArea Is Chart1.ChartAreas("ChartArea1") Then
                If IsMouseDown = True Then
                    IsMouseDown = False
                    IsMouseMoving = False
                    IsMouseUp = True
                    UpPoint = New Point(e.X, e.Y)
                    Chart1.Refresh()
                End If
            End If
        End Sub
    
        Private Sub Chart1_Paint(sender As Object, e As PaintEventArgs)
            If IsMouseMoving = True Then
                e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
                Using Pen1 As New Pen(Brushes.Silver, 1)
                    e.Graphics.DrawLine(Pen1, DownPoint, MovingPoint)
                End Using
            ElseIf IsMouseUp = True Then
                e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
                Using Pen1 As New Pen(Brushes.Red, 3)
                    e.Graphics.DrawLine(Pen1, DownPoint, UpPoint)
                End Using
            End If
        End Sub
    
    End Class


    La vida loca

    • Edited by Mr. Monkeyboy Friday, April 29, 2016 2:35 PM
    • Marked as answer by ali-IRAN Saturday, April 30, 2016 8:34 AM
    Friday, April 29, 2016 2:23 PM

All replies

  • Hi,

    draw to the chart in the PostPaint event. Here's an example drawing a line. Its location is based on a dgv record index.

    Add a Reference to the System.Windows.Form.DataVisualization.dll

    Option Strict On
    
    Partial Public Class Form1
        Inherits Form
        Private _x As Integer = -1
        Private chart1 As System.Windows.Forms.DataVisualization.Charting.Chart
        Private dgv As New DataGridView()
        Private _dontDo As Boolean
    
        Public Sub New()
            InitializeComponent()
            Me.KeyPreview = True
    
            Init()
        End Sub
    
        Private Sub Init()
            Dim chartArea1 As New System.Windows.Forms.DataVisualization.Charting.ChartArea()
            Dim legend1 As New System.Windows.Forms.DataVisualization.Charting.Legend()
            Dim series1 As New System.Windows.Forms.DataVisualization.Charting.Series()
    
            dgv.Location = New Point(624, 45)
            dgv.ClientSize = New System.Drawing.Size(350, 360)
            Me.Controls.Add(dgv)
    
            Dim dt As New DataTable()
            dt.Columns.Add("col1")
            dt.Columns.Add("col2")
    
            For i As Integer = 1 To 10
                Dim dr As DataRow = dt.NewRow()
                dr(0) = i.ToString()
                dr(1) = (i * 4).ToString()
                dt.Rows.Add(dr)
            Next
    
            dgv.DataSource = dt.DefaultView
    
            AddHandler Me.dgv.SelectionChanged, AddressOf dgv_SelectionChanged
            AddHandler Me.dgv.CellValidating, AddressOf dgv_CellValidating
    
            Me.chart1 = New System.Windows.Forms.DataVisualization.Charting.Chart()
    
            chartArea1.Name = "ChartArea1"
            Me.chart1.ChartAreas.Add(chartArea1)
            legend1.Name = "Legend1"
            Me.chart1.Legends.Add(legend1)
            Me.chart1.Location = New System.Drawing.Point(32, 45)
            Me.chart1.Name = "chart1"
            series1.ChartArea = "ChartArea1"
            series1.Legend = "Legend1"
            series1.Name = "Series123"
    
            Me.chart1.Series.Add(series1)
            Me.chart1.Size = New System.Drawing.Size(584, 360)
            Me.chart1.TabIndex = 0
            Me.chart1.Text = "chart1"
            AddHandler Me.chart1.PostPaint, AddressOf Me.chart1_PostPaint
            AddHandler Me.chart1.KeyDown, AddressOf Me.chart1_KeyDown
    
            chart1.DataSource = dt
            chart1.Series(0).XValueMember = "col1"
            chart1.Series(0).YValueMembers = "col2"
            chart1.DataBind()
    
            Me.Controls.Add(Me.chart1)
            Me.ClientSize = New System.Drawing.Size(1024, 474)
    
            AddHandler Me.chart1.Click, Sub(s, e)
                                            chart1.Focus()
                                        End Sub
    
            Me.chart1.[Select]()
        End Sub
    
        Private Sub dgv_CellValidating(sender As Object, e As DataGridViewCellValidatingEventArgs)
            If Me.Visible AndAlso dgv.DataSource IsNot Nothing Then
                chart1.DataBind()
            End If
        End Sub
    
        Private Sub dgv_SelectionChanged(sender As Object, e As EventArgs)
            If Not _dontDo Then
                If dgv.SelectedRows.Count > 0 Then
                    _x = dgv.SelectedRows(0).Index + 1
    
                ElseIf dgv.SelectedCells.Count > 0 Then
                    _x = dgv.SelectedCells(0).RowIndex + 1
                End If
    
                Me.chart1.Invalidate()
    
                Me.chart1.[Select]()
            End If
        End Sub
    
        'controlKey must be held down
        Private Sub chart1_KeyDown(sender As Object, e As KeyEventArgs)
            If e.KeyData = (Keys.Right Or Keys.Control) Then
                _x += 1
    
                _x = Math.Min(Me.chart1.Series(0).Points.Count, _x)
    
                Me.chart1.Invalidate()
            End If
    
            If e.KeyData = (Keys.Left Or Keys.Control) Then
                _x -= 1
    
                _x = Math.Max(_x, 0)
    
                Me.chart1.Invalidate()
            End If
        End Sub
    
        Private Sub chart1_PostPaint(sender As Object, e As System.Windows.Forms.DataVisualization.Charting.ChartPaintEventArgs)
            Dim o As Object = e.ChartElement
    
            If o.[GetType]().Equals(GetType(System.Windows.Forms.DataVisualization.Charting.Series)) Then
                Dim xVal As Single = CSng(e.ChartGraphics.GetPositionFromAxis(e.Chart.ChartAreas(0).Name, System.Windows.Forms.DataVisualization.Charting.AxisName.X, _x))
                Dim pt As PointF = e.ChartGraphics.GetAbsolutePoint(New PointF(xVal, 0))
                e.ChartGraphics.Graphics.DrawLine(Pens.Red, pt, New PointF(pt.X, e.Chart.ClientSize.Height))
    
                If _x - 1 > -1 AndAlso _x - 1 < dgv.Rows.Count Then
                    _dontDo = True
                    dgv.ClearSelection()
                    Me.dgv.Rows(_x - 1).Selected = True
                    _dontDo = False
                End If
            End If
        End Sub
    End Class
    

    Regards,

      Thorsten

    Friday, April 29, 2016 12:16 PM
  • I try Draw a line on the chart area with this code :

    If the mouse position is outside the chart area, how will you calculate the point at which to draw the line?

    If you want to draw the line between the points, but only draw that portion that is inside the chart area, then you have a simple calculation in plane geometry that involves calculating the intersection point of the line and the chart borders.  Then draw the line between those intersection points. 

    http://stackoverflow.com/questions/1585525/how-to-find-the-intersection-point-between-a-line-and-a-rectangle

    If you want to use the graphics object created from the chart instead of the form, then you need to convert the e.x and e.y mouse position information from screen coordinates to control coordinates.  See:

    https://msdn.microsoft.com/en-us/library/system.windows.forms.control.pointtoclient%28v=vs.110%29.aspx

    But in any case I believe you will have a lot of trouble getting that code to work using CreateGraphics.  That code should be in the control paint event handler.

    Friday, April 29, 2016 12:20 PM
  • This code will allow the mouse to draw a line within a ChartArea using a HitTest. The logic for the Mouse Events could probably be better though. I forgot to add logic if you mouse down within a ChartArea and MouseUp outside a ChartArea though which will probably leave the silver line on the Chart until you move the mouse back into the Chart area and mouse down and mouse up or something.

    I've also never had two chart areas where one is on one area of the Chart and the other has different x and y axis minimum and maximums so I didn't think about that when I did the logic. But you should be able to alter the logic using the HitTest logic in case you move the mouse out of one chart area while holding the left button down into another chart area.

    First place the cursor on the Chart and select left mouse button and hold it down, move the mouse to wherever you want to draw a line from and to and while moving the mouse a 1 pixel width silver line will appear following the mouse cursors point from the original starting point. When you get to where the end of the line should be then let the left mouse button up and the line will be drawn in 3 pixel width red line from starting point to end point.

    Next time mouse left button goes down in ChartArea it clears the line. The next mouse left button down in the ChartArea starts the process over.

    The pictures 2nd and 3rd images don't match with regard to the silver lines start point cause I was taking screenshots and had to start over for the 3rd image so the start point differs from the 2nd image.

    Option Strict On
    
    Imports System.Windows.Forms.DataVisualization.Charting
    
    Public Class Form1
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.Location = New Point(CInt((Screen.PrimaryScreen.WorkingArea.Width / 2) - (Me.Width / 2)), CInt((Screen.PrimaryScreen.WorkingArea.Height / 2) - (Me.Height / 2)))
            Chart1.Series.Clear()
            Chart1.ChartAreas.Clear()
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            IsMouseDown = False
            IsMouseMoving = False
            IsMouseUp = False
            RemoveHandler Chart1.MouseDown, AddressOf Chart1_MouseDown
            RemoveHandler Chart1.MouseMove, AddressOf Chart1_MouseMove
            RemoveHandler Chart1.MouseUp, AddressOf Chart1_MouseUp
            RemoveHandler Chart1.Paint, AddressOf Chart1_Paint
            Chart1.Series.Clear()
            Chart1.ChartAreas.Clear()
            Chart1.ChartAreas.Add("ChartArea1")
            Chart1.ChartAreas("ChartArea1").AxisX.Minimum = 0
            Chart1.ChartAreas("ChartArea1").AxisX.Maximum = 100
            Chart1.ChartAreas("ChartArea1").AxisX.Interval = 10
            Chart1.ChartAreas("ChartArea1").AxisY.Minimum = 0
            Chart1.ChartAreas("ChartArea1").AxisY.Maximum = 100
            Chart1.ChartAreas("ChartArea1").AxisY.Interval = 10
            Chart1.Series.Add("Test")
            Chart1.Series("Test").ChartType = SeriesChartType.Line
            Chart1.Series("Test").Color = Color.Lime
            Chart1.Series("Test").BorderWidth = 5 ' Set the lines width
            Chart1.Series("Test").MarkerColor = Color.Magenta
            Chart1.Series("Test").MarkerBorderColor = Color.Black
            Chart1.Series("Test").MarkerBorderWidth = 1
            Chart1.Series("Test").MarkerSize = 12
            Chart1.Series("Test").MarkerStyle = MarkerStyle.Star10
            Chart1.Series("Test").Points.AddXY(10, 10)
            Chart1.Series("Test").Points.AddXY(90, 90)
    
            AddHandler Chart1.MouseDown, AddressOf Chart1_MouseDown
            AddHandler Chart1.MouseMove, AddressOf Chart1_MouseMove
            AddHandler Chart1.MouseUp, AddressOf Chart1_MouseUp
            AddHandler Chart1.Paint, AddressOf Chart1_Paint
        End Sub
    
        Dim DownPoint As Point
        Dim IsMouseDown As Boolean = False
        Dim MovingPoint As Point
        Dim IsMouseMoving As Boolean = False
        Dim UpPoint As Point
        Dim IsMouseUp As Boolean = False
        
    
        Private Sub Chart1_MouseDown(sender As Object, e As MouseEventArgs)
            Dim ChartHitTest As HitTestResult = Chart1.HitTest(e.X, e.Y)
            If ChartHitTest.ChartArea Is Chart1.ChartAreas("ChartArea1") Then
                If IsMouseDown = False And IsMouseUp = False Then
                    DownPoint = New Point(e.X, e.Y)
                    IsMouseDown = True
                Else
                    IsMouseUp = False
                    Chart1.Refresh()
                End If
            End If
        End Sub
    
        Private Sub Chart1_MouseMove(sender As Object, e As MouseEventArgs)
            Dim ChartHitTest As HitTestResult = Chart1.HitTest(e.X, e.Y)
            If ChartHitTest.ChartArea Is Chart1.ChartAreas("ChartArea1") Then
                If IsMouseDown = True Then
                    IsMouseMoving = True
                    MovingPoint = New Point(e.X, e.Y)
                    Chart1.Refresh()
                End If
            End If
        End Sub
    
        Private Sub Chart1_MouseUp(sender As Object, e As MouseEventArgs)
            Dim ChartHitTest As HitTestResult = Chart1.HitTest(e.X, e.Y)
            If ChartHitTest.ChartArea Is Chart1.ChartAreas("ChartArea1") Then
                If IsMouseDown = True Then
                    IsMouseDown = False
                    IsMouseMoving = False
                    IsMouseUp = True
                    UpPoint = New Point(e.X, e.Y)
                    Chart1.Refresh()
                End If
            End If
        End Sub
    
        Private Sub Chart1_Paint(sender As Object, e As PaintEventArgs)
            If IsMouseMoving = True Then
                e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
                Using Pen1 As New Pen(Brushes.Silver, 1)
                    e.Graphics.DrawLine(Pen1, DownPoint, MovingPoint)
                End Using
            ElseIf IsMouseUp = True Then
                e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
                Using Pen1 As New Pen(Brushes.Red, 3)
                    e.Graphics.DrawLine(Pen1, DownPoint, UpPoint)
                End Using
            End If
        End Sub
    
    End Class


    La vida loca

    • Edited by Mr. Monkeyboy Friday, April 29, 2016 2:35 PM
    • Marked as answer by ali-IRAN Saturday, April 30, 2016 8:34 AM
    Friday, April 29, 2016 2:23 PM