ASE Home Page Products Download Purchase Support About ASE
ChartDirector Support
Forum HomeForum Home   SearchSearch

Message ListMessage List     Post MessagePost Message

  Add zoom to real time chart
Posted by Hun Siong on Nov-19-2013 21:00
Dear Sir/Madam,

Please help.. Urgent.. I am having difficulty adding zoom feature to the real time directory chart. Below is my code. Please advise anything I have missed out. The zoom feature is totally not working.

Thank You.


Imports ChartDirector

Public Class FrmZoomScrollTrack2

    ' Data arrays
    'Dim timeStamps As DateTime()
    'Dim dataSeriesA As Double()
    'Dim dataSeriesB As Double()
    'Dim dataSeriesC As Double()
    ' The data arrays that store the visible data. The data arrays are updated in realtime. In
    ' this demo, we plot the last 240 samples.
    Private Const sampleSize As Integer = 240
    Private dataSeriesA(sampleSize - 1) As Double
    Private dataSeriesB(sampleSize - 1) As Double
    Private dataSeriesC(sampleSize - 1) As Double
    Private timeStamps(sampleSize - 1) As Date

    ' The index of the array position to which new data values are added.
    Private currentIndex As Integer = 0

    ' In this demo, we use a data generator driven by a timer to generate realtime data. The
    ' nextDataTime is an internal variable used by the data generator to keep track of which
    ' values to generate next.
    Private nextDataTime As DateTime = New DateTime((Now.Ticks \\ 10000000) * 10000000)

    ' Flag to indicated if initialization has been completed. Prevents events from firing before
    ' controls are properly initialized.
    Private hasFinishedInitialization As Boolean

    Private Sub FrmZoomScrollTrack2_Load(ByVal sender As Object, ByVal e As EventArgs) _
        Handles MyBase.Load

        ' Load the data
        'loadData()

        '' Initialize the WinChartViewer
        'initChartViewer(winChartViewer1)

        '' Can handle events now
        'hasFinishedInitialization = True

        '' Trigger the ViewPortChanged event to draw the chart

        ' Initialize the view port to show the latest 20% of the time range

        winChartViewer1.setFullRange("x", 0, timeStamps.Length - 1)

        ' Initialize the view port to show the latest 250 points
        winChartViewer1.ViewPortWidth = timeStamps.Length
        winChartViewer1.ViewPortLeft = 1 - winChartViewer1.ViewPortWidth

        'Set the maximum zoom to 10 points
        winChartViewer1.ZoomInWidthLimit = 10 / timeStamps.Length
        winChartViewer1.ZoomDirection = WinChartDirection.HorizontalVertical

        ' Initially set the mouse usage to "Pointer" mode (Drag to Scroll mode)
        ' Data generation rate
        dataRateTimer.Interval = 250

        ' Chart update rate
        chartUpdateTimer.Interval = CInt(samplePeriod.Value)

        ' Initialize data buffer. In this demo, we just set the initial state to no data.
        Dim i As Integer
        For i = 0 To UBound(timeStamps)
            timeStamps(i) = DateTime.MinValue
        Next


        ' Set the maximum zoom to 10 points
        'winChartViewer1.ZoomInWidthLimit = 10.0 / timeStamps.Length

        ' Initially set the mouse usage to "Pointer" mode (Drag to Scroll mode)
        pointerPB.Checked = True
        ' Enable RunPB button
        runPB.Checked = True

        ' Now can start the timers for data collection and chart update
        dataRateTimer.Start()
        chartUpdateTimer.Start()

        'winChartViewer1.updateViewPort(True, True)

    End Sub

    '
    ' Load the data
    '
    Private Sub loadData()

        ' In this example, we just use random numbers as data.
        Dim r As RanSeries = New RanSeries(127)
        timeStamps = r.getDateSeries(1827, New DateTime(2007, 1, 1), 86400)
        dataSeriesA = r.getSeries2(1827, 150, -10, 10)
        dataSeriesB = r.getSeries2(1827, 200, -10, 10)
        dataSeriesC = r.getSeries2(1827, 250, -8, 8)

    End Sub

    '
    ' Initialize the WinChartViewer
    '
    Private Sub initChartViewer(ByVal viewer As WinChartViewer)

        ' Set the full x range to be the duration of the data
        viewer.SetFullRange("x", timeStamps(0), timeStamps(timeStamps.Length - 1))

        ' Initialize the view port to show the latest 20% of the time range
        viewer.ViewPortWidth = 0.2
        viewer.ViewPortLeft = 1 - viewer.ViewPortWidth

        ' Set the maximum zoom to 10 points
        viewer.ZoomInWidthLimit = 10.0 / timeStamps.Length

        ' Initially set the mouse usage to "Pointer" mode (Drag to Scroll mode)
        pointerPB.Checked = True

    End Sub

    '
    ' The ViewPortChanged event handler. This event occurs if the user scrolls or zooms in
    ' or out the chart by dragging or clicking on the chart. It can also be triggered by
    ' calling WinChartViewer.updateViewPort.
    '
    Private Sub winChartViewer1_ViewPortChanged(ByVal sender As Object, _
        ByVal e As WinViewPortEventArgs) Handles winChartViewer1.ViewPortChanged

        ' In addition to updating the chart, we may also need to update other controls that
        ' changes based on the view port.
        'updateControls(winChartViewer1)

        ' Update the chart if necessary
        If e.NeedUpdateChart Then
            drawChart(winChartViewer1)
        End If

        ' We need to update the track line too. If the mouse is moving on the chart (eg. if
        ' the user drags the mouse on the chart to scroll it), the track line will be updated
        ' in the MouseMovePlotArea event. Otherwise, we need to update the track line here.
        If (Not winChartViewer1.IsInMouseMoveEvent) And winChartViewer1.IsMouseOnPlotArea Then
            trackLineLegend(winChartViewer1.Chart, winChartViewer1.PlotAreaMouseX)
            winChartViewer1.updateDisplay()
        End If
        'drawChart(winChartViewer1)
    End Sub

    '
    ' Update controls when the view port changed
    '
    Private Sub updateControls(ByVal viewer As WinChartViewer)

        ' Update the start date and end date control to reflect the view port.
        startDateCtrl.Value = Chart.NTime(viewer.GetValueAtViewPort("x", viewer.ViewPortLeft))
        endDateCtrl.Value = Chart.NTime(viewer.GetValueAtViewPort("x", viewer.ViewPortLeft + _
            viewer.ViewPortWidth))

        ' Update the scroll bar to reflect the view port position and width of the view port.
        hScrollBar1.Enabled = winChartViewer1.ViewPortWidth < 1
        hScrollBar1.LargeChange = Math.Ceiling(winChartViewer1.ViewPortWidth * _
            (hScrollBar1.Maximum - hScrollBar1.Minimum))
        hScrollBar1.SmallChange = Math.Ceiling(hScrollBar1.LargeChange * 0.1)
        hScrollBar1.Value = Math.Round(winChartViewer1.ViewPortLeft * _
            (hScrollBar1.Maximum - hScrollBar1.Minimum)) + hScrollBar1.Minimum

    End Sub

    '
    ' Draw the chart and display it in the given viewer.
    '
    Private Sub drawChart(ByVal viewer As WinChartViewer)

        ' Create an XYChart object 600 x 270 pixels in size, with light grey (f4f4f4)
        ' background, black (000000) border, 1 pixel raised effect, and with a rounded frame.
        Dim c As XYChart = New XYChart(640, 350, &HF4F4F4, &H0, 1)
        c.setRoundedFrame(Chart.CColor(BackColor))

        ' Set the plotarea at (55, 55) and of size 520 x 185 pixels. Use white (ffffff)
        ' background. Enable both horizontal and vertical grids by setting their colors to
        ' grey (cccccc). Set clipping mode to clip the data lines to the plot area.
        c.setPlotArea(55, 55, 520, 185, &HFFFFFF, -1, -1, &HCCCCCC, &HCCCCCC)
        c.setClipping()

        ' Add a title to the chart using 15 pts Times New Roman Bold Italic font, with a light
        ' grey (dddddd) background, black (000000) border, and a glass like raised effect.
        c.addTitle("Field Intensity at Observation Satellite", "Times New Roman Bold Italic", 15 _
            ).setBackground(&HDDDDDD, &H0, Chart.glassEffect())

        ' Set the reference font size of the legend box
        c.getLegend().setFontSize(8)

        ' Configure the y-axis with a 10pts Arial Bold axis title
        c.yAxis().setTitle("Intensity (V/m)", "Arial Bold", 10)

        ' Configure the x-axis to auto-scale with at least 75 pixels between major tick and 15
        ' pixels between minor ticks. This shows more minor grid lines on the chart.
        c.xAxis().setTickDensity(75, 15)

        ' Set the axes width to 2 pixels
        c.xAxis().setWidth(2)
        c.yAxis().setWidth(2)

        ' Now we add the data to the chart
        Dim firstTime As DateTime = timeStamps(0)
        If firstTime <> DateTime.MinValue Then
            '
            ' Set up the x-axis scale. In this demo, we set the x-axis to show the 240 samples,
            ' with 250ms per sample.
            c.xAxis().setDateScale(firstTime, firstTime.AddSeconds( _
                dataRateTimer.Interval * timeStamps.Length / 1000))

            ' Set the x-axis label format
            c.xAxis().setLabelFormat("{value|hh:nn:ss}")

            ' Create a line layer to plot the lines
            Dim layer As LineLayer = c.addLineLayer2()
            layer.setFastLineMode()
            ' The x-coordinates are the timeStamps.
            layer.setXData(timeStamps)

            ' The 3 data series are used to draw 3 lines.
            layer.addDataSet(dataSeriesA, &HFF0000, "Alpha")
            layer.addDataSet(dataSeriesB, &HCC00, "Beta")
            layer.addDataSet(dataSeriesC, &HFF, "Gamma")
        End If


        ' Include track line with legend. If the mouse is on the plot area, show the track
        ' line with legend at the mouse position; otherwise, show them for the latest data
        ' values (that is, at the rightmost position).
        trackLineLegend(c, IIf(viewer.IsMouseOnPlotArea, viewer.PlotAreaMouseX, _
            c.getPlotArea().getRightX()))


        'viewer.syncLinearAxisWithViewPort("x", c.xAxis())
        'viewer.syncLinearAxisWithViewPort("y", c.yAxis())
        'viewer.syncDateAxisWithViewPort("x", c.xAxis())
        ' Assign the chart to the WinChartViewer
        viewer.Chart = c

    End Sub
    ''
    '' Draw the chart.
    ''
    'Private Sub drawChart(ByVal viewer As WinChartViewer)

    '    ' Get the start date and end date that are visible on the chart.
    '    Dim viewPortStartDate As DateTime = Chart.NTime(viewer.GetValueAtViewPort("x", viewer.ViewPortLeft))
    '    Dim viewPortEndDate As DateTime = Chart.NTime(viewer.GetValueAtViewPort("x", viewer.ViewPortLeft + _
    '        viewer.ViewPortWidth))

    '    ' Get the array indexes that corresponds to the visible start and end dates
    '    Dim startIndex As Integer = Math.Floor(Chart.bSearch(timeStamps, viewPortStartDate))
    '    Dim endIndex As Integer = Math.Ceiling(Chart.bSearch(timeStamps, viewPortEndDate))
    '    Dim noOfPoints As Integer = endIndex - startIndex + 1

    '    ' Extract the part of the data array that are visible.
    '    Dim viewPortTimeStamps As DateTime() = Chart.arraySlice(timeStamps, startIndex, noOfPoints)
    '    Dim viewPortDataSeriesA As Double() = Chart.arraySlice(dataSeriesA, startIndex, noOfPoints)
    '    Dim viewPortDataSeriesB As Double() = Chart.arraySlice(dataSeriesB, startIndex, noOfPoints)
    '    Dim viewPortDataSeriesC As Double() = Chart.arraySlice(dataSeriesC, startIndex, noOfPoints)

    '    '
    '    ' At this stage, we have extracted the visible data. We can use those data to plot the chart.
    '    '

    '    '================================================================================
    '    ' Configure overall chart appearance.
    '    '================================================================================

    '    ' Create an XYChart object of size 640 x 350 pixels
    '    Dim c As XYChart = New XYChart(640, 350)

    '    ' Set the plotarea at (55, 50) with width 80 pixels less than chart width, and height 85 pixels
    '    ' less than chart height. Use a vertical gradient from light blue (f0f6ff) to sky blue (a0c0ff)
    '    ' as background. Set border to transparent and grid lines to white (ffffff).
    '    c.setPlotArea(55, 50, c.getWidth() - 80, c.getHeight() - 85, c.linearGradientColor(0, 50, 0, _
    '        c.getHeight() - 35, &HF0F6FF, &HA0C0FF), -1, Chart.Transparent, &HFFFFFF, &HFFFFFF)

    '    ' As the data can lie outside the plotarea in a zoomed chart, we need enable clipping.
    '    c.setClipping()

    '    ' Add a title to the chart using 18 pts Times New Roman Bold Italic font
    '    c.addTitle("   Zooming and Scrolling with Track Line (2)", "Times New Roman Bold Italic", 18)

    '    ' Add a legend box at (55, 25) using horizontal layout. Use 8pts Arial Bold as font. Set the
    '    ' background and border color to Transparent and use line style legend key.
    '    Dim b As LegendBox = c.addLegend(55, 25, False, "Arial Bold", 8)
    '    b.setBackground(Chart.Transparent)
    '    b.setLineStyleKey()

    '    ' Set the axis stem to transparent
    '    c.xAxis().setColors(Chart.Transparent)
    '    c.yAxis().setColors(Chart.Transparent)

    '    ' Add axis title using 10pts Arial Bold Italic font
    '    c.yAxis().setTitle("Ionic Temperature (C)", "Arial Bold Italic", 10)

    '    '================================================================================
    '    ' Add data to chart
    '    '================================================================================

    '    '
    '    ' In this example, we represent the data by lines. You may modify the code below to use other
    '    ' representations (areas, scatter plot, etc).
    '    '

    '    ' Add a line layer for the lines, using a line width of 2 pixels
    '    Dim layer As LineLayer = c.addLineLayer2()
    '    Layer.setLineWidth(2)

    '    ' In this demo, we do not have too many data points. In real code, the chart may contain a lot
    '    ' of data points when fully zoomed out - much more than the number of horizontal pixels in this
    '    ' plot area. So it is a good idea to use fast line mode.
    '    Layer.setFastLineMode()

    '    ' Now we add the 3 data series to a line layer, using the color red (ff33333), green (008800)
    '    ' and blue (3333cc)
    '    Layer.setXData(viewPortTimeStamps)
    '    ' Layer.addDataSet(viewPortDataSeriesA, &HFF3333, "Alpha")
    '    ' Layer.addDataSet(viewPortDataSeriesB, &H008800, "Beta")
    '    ' layer.addDataSet(viewPortDataSeriesC, &H3333CC, "Gamma")
    '    ' The 3 data series are used to draw 3 lines.
    '    layer.addDataSet(dataSeriesA, &HFF0000, "Alpha")
    '    layer.addDataSet(dataSeriesB, &HCC00, "Beta")
    '    layer.addDataSet(dataSeriesC, &HFF, "Gamma")

    '    '================================================================================
    '    ' Configure axis scale and labelling
    '    '================================================================================

    '    ' Set the x-axis as a date/time axis with the scale according to the view port x range.
    '    viewer.SyncDateAxisWithViewPort("x", c.xAxis())

    '    '
    '    ' In this demo, the time range can be from a few years to a few days. We demonstrate how to set
    '    ' up different date/time format based on the time range.
    '    '

    '    ' If all ticks are yearly aligned, then we use "yyyy" as the label format.
    '    c.xAxis().setFormatCondition("align", 360 * 86400)
    '    c.xAxis().setLabelFormat("{value|yyyy}")

    '    ' If all ticks are monthly aligned, then we use "mmm yyyy" in bold font as the first label of a
    '    ' year, and "mmm" for other labels.
    '    c.xAxis().setFormatCondition("align", 30 * 86400)
    '    c.xAxis().setMultiFormat(Chart.StartOfYearFilter(), "<*font=bold*>{value|mmm yyyy}", _
    '        Chart.AllPassFilter(), "{value|mmm}")

    '    ' If all ticks are daily algined, then we use "mmm dd<*br*>yyyy" in bold font as the first
    '    ' label of a year, and "mmm dd" in bold font as the first label of a month, and "dd" for other
    '    ' labels.
    '    c.xAxis().setFormatCondition("align", 86400)
    '    c.xAxis().setMultiFormat(Chart.StartOfYearFilter(), _
    '        "<*block,halign=left*><*font=bold*>{value|mmm dd<*br*>yyyy}", Chart.StartOfMonthFilter(), _
    '        "<*font=bold*>{value|mmm dd}")
    '    c.xAxis().setMultiFormat2(Chart.AllPassFilter(), "{value|dd}")

    '    ' For all other cases (sub-daily ticks), use "hh:nn<*br*>mmm dd" for the first label of a day,
    '    ' and "hh:nn" for other labels.
    '    c.xAxis().setFormatCondition("else")
    '    c.xAxis().setMultiFormat(Chart.StartOfDayFilter(), "<*font=bold*>{value|hh:nn<*br*>mmm dd}", _
    '        Chart.AllPassFilter(), "{value|hh:nn}")

    '    '================================================================================
    '    ' Output the chart
    '    '================================================================================

    '    viewer.Chart = c

    'End Sub

    '
    ' Pointer (Drag to Scroll) button event handler
    '
    Private Sub pointerPB_CheckedChanged(ByVal sender As Object, ByVal e As EventArgs) _
        Handles pointerPB.CheckedChanged

        If sender.Checked Then
            winChartViewer1.MouseUsage = WinChartMouseUsage.ScrollOnDrag
        End If

    End Sub

    '
    ' Zoom In button event handler
    '
    Private Sub zoomInPB_CheckedChanged(ByVal sender As Object, ByVal e As EventArgs) _
        Handles zoomInPB.CheckedChanged

        If sender.Checked Then
            winChartViewer1.MouseUsage = WinChartMouseUsage.ZoomIn
        End If

    End Sub

    '
    ' Zoom Out button event handler
    '
    Private Sub zoomOutPB_CheckedChanged(ByVal sender As Object, ByVal e As EventArgs) _
        Handles zoomOutPB.CheckedChanged

        If sender.Checked Then
            winChartViewer1.MouseUsage = WinChartMouseUsage.ZoomOut
        End If

    End Sub

    '
    ' The scroll bar event handler
    '
    Private Sub hScrollBar1_ValueChanged(ByVal sender As Object, ByVal e As EventArgs) _
        Handles hScrollBar1.ValueChanged

        ' When the view port is changed (user drags on the chart to scroll), the scroll bar will get
        ' updated. When the scroll bar changes (eg. user drags on the scroll bar), the view port will
        ' get updated. This creates an infinite loop. To avoid this, the scroll bar can update the
        ' view port only if the view port is not updating the scroll bar.
        If hasFinishedInitialization And Not winChartViewer1.IsInViewPortChangedEvent Then
            ' Set the view port based on the scroll bar
            winChartViewer1.ViewPortLeft = (hScrollBar1.Value - hScrollBar1.Minimum) / _
                (hScrollBar1.Maximum - hScrollBar1.Minimum)

            ' Trigger a view port changed event to update the chart
            winChartViewer1.updateViewPort(True, False)
        End If

    End Sub

    '
    ' Start Date control event handler
    '
    Private Sub startDateCtrl_ValueChanged(ByVal sender As Object, ByVal e As EventArgs) _
        Handles startDateCtrl.ValueChanged

        ' The date control can update the view port only if it is not currently being updated in the
        ' view port changed event (that is, only if the date is changed due to user action).
        If hasFinishedInitialization And Not winChartViewer1.IsInViewPortChangedEvent Then
            ' The updated view port width
            Dim vpWidth As Double = winChartViewer1.ViewPortLeft + winChartViewer1.ViewPortWidth - _
                winChartViewer1.GetViewPortAtValue("x", Chart.CTime(startDateCtrl.Value))

            ' Make sure the updated view port width is within bounds
            vpWidth = Math.Max(winChartViewer1.ZoomInWidthLimit, Math.Min(vpWidth, _
                winChartViewer1.ViewPortLeft + winChartViewer1.ViewPortWidth))

            ' Update view port and trigger a view port changed event to update the chart
            winChartViewer1.ViewPortLeft += winChartViewer1.ViewPortWidth - vpWidth
            winChartViewer1.ViewPortWidth = vpWidth
            winChartViewer1.updateViewPort(True, False)
        End If

    End Sub

    '
    ' End Date control event handler
    '
    Private Sub endDateCtrl_ValueChanged(ByVal sender As Object, ByVal e As EventArgs) _
        Handles endDateCtrl.ValueChanged

        ' The date control can update the view port only if it is not currently being updated in the
        ' view port changed event (that is, only if the date is changed due to user action).
        If hasFinishedInitialization And Not winChartViewer1.IsInViewPortChangedEvent Then
            ' The updated view port width
            Dim vpWidth As Double = winChartViewer1.GetViewPortAtValue("x", _
                Chart.CTime(endDateCtrl.Value)) - winChartViewer1.ViewPortLeft

            ' Make sure the updated view port width is within bounds
            vpWidth = Math.Max(winChartViewer1.ZoomInWidthLimit, Math.Min(vpWidth, _
                1 - winChartViewer1.ViewPortLeft))

            ' Update view port and trigger a view port changed event to update the chart
            winChartViewer1.ViewPortWidth = vpWidth
            winChartViewer1.updateViewPort(True, False)
        End If

    End Sub

    '
    ' We want to use the mouse wheel for zoom in/out when the mouse is over the chart. To to do, we need
    ' to set the WinChartViewer to be the "active control" when the mouse enters the chart.
    '

    ' Variable to save the original active control
    Private activeControlSave As Control = Nothing

    '
    ' Mouse Enter event handler
    '
    Private Sub winChartViewer1_MouseEnter(ByVal sender As Object, ByVal e As EventArgs) _
        Handles winChartViewer1.MouseEnter

        ' Save the original active control and set the WinChartViewer to be the active control, so that
        ' the WinChartViewer can receive the mouse wheel event.
        activeControlSave = winChartViewer1.FindForm().ActiveControl
        winChartViewer1.FindForm().ActiveControl = winChartViewer1

    End Sub

    '
    ' Mouse Leave event handler
    '
    Private Sub winChartViewer1_MouseLeave(ByVal sender As Object, ByVal e As EventArgs) _
        Handles winChartViewer1.MouseLeave

        ' Restore the original active control.
        winChartViewer1.FindForm().ActiveControl = activeControlSave

    End Sub
    '
    ' Mouse Wheel event handler
    '
    Private Sub winChartViewer1_MouseWheel(ByVal sender As Object, _
        ByVal e As System.Windows.Forms.MouseEventArgs) Handles winChartViewer1.MouseWheel

        ' We zoom in or out by 10% depending on the mouse wheel direction.
        Dim rx As Double = IIf(e.Delta > 0, 0.9, 1 / 0.9)
        Dim ry As Double = rx

        ' We do not zoom in beyond the zoom in width or height limit.
        rx = Math.Max(rx, winChartViewer1.ZoomInWidthLimit / winChartViewer1.ViewPortWidth)
        ry = Math.Max(ry, winChartViewer1.ZoomInWidthLimit / winChartViewer1.ViewPortHeight)
        If rx = 1 And ry = 1 Then
            Return
        End If

        Dim c As XYChart = winChartViewer1.Chart

        '
        ' Set the view port position and size so that it is zoom in/out around the mouse by the
        ' desired ratio.
        '

        Dim mouseOffset As Double = (winChartViewer1.ChartMouseX - c.getPlotArea().getLeftX()) / _
            c.getPlotArea().getWidth()
        winChartViewer1.ViewPortLeft += mouseOffset * (1 - rx) * winChartViewer1.ViewPortWidth
        winChartViewer1.ViewPortWidth *= rx

        Dim mouseOffsetY As Double = (winChartViewer1.ChartMouseY - c.getPlotArea().getTopY()) / _
            c.getPlotArea().getHeight()
        winChartViewer1.ViewPortTop += mouseOffsetY * (1 - ry) * winChartViewer1.ViewPortHeight
        winChartViewer1.ViewPortHeight *= ry

        ' Trigger a view port changed event to update the chart
        winChartViewer1.updateViewPort(True, False)

    End Sub

    ''
    '' Mouse Wheel event handler
    ''
    'Private Sub winChartViewer1_MouseWheel(ByVal sender As Object, _
    '    ByVal e As System.Windows.Forms.MouseEventArgs) Handles winChartViewer1.MouseWheel

    '    ' We zoom in or out by 10% depending on the mouse wheel direction.
    '    Dim r As Double = IIf(e.Delta > 0, 0.9, 1 / 0.9)
    '    ' We do not zoom in beyond the zoom in width limit.
    '    If ((r = Math.Max(r, winChartViewer1.ZoomInWidthLimit / winChartViewer1.ViewPortWidth)) = 1) Then
    '        Return
    '    End If

    '    Dim c As XYChart = winChartViewer1.Chart

    '    ' Set the view port position and size so that it is zoom in/out around the mouse by the
    '    ' desired ratio.
    '    Dim mouseOffset As Double = (e.X - c.getPlotArea().getLeftX()) / c.getPlotArea().getWidth()
    '    winChartViewer1.ViewPortLeft += mouseOffset * (1 - r) * winChartViewer1.ViewPortWidth
    '    winChartViewer1.ViewPortWidth *= r

    '    ' Trigger a view port changed event to update the chart
    '    winChartViewer1.updateViewPort(True, False)

    'End Sub

    '
    ' Draw track cursor when mouse is moving over plotarea
    '
    Private Sub winChartViewer1_MouseMovePlotArea(ByVal sender As Object, _
        ByVal e As System.Windows.Forms.MouseEventArgs) Handles winChartViewer1.MouseMovePlotArea

        'Dim viewer As WinChartViewer = sender
        'trackLineLabel(viewer.Chart, viewer.PlotAreaMouseX)
        'viewer.updateDisplay()

        '' Hide the track cursor when the mouse leaves the plot area
        'viewer.removeDynamicLayer("MouseLeavePlotArea")

        Dim viewer As WinChartViewer = sender
        trackLineLegend(viewer.Chart, viewer.PlotAreaMouseX)
        viewer.updateDisplay()

    End Sub

    '
    ' Draw track line with data labels
    '
    Private Sub trackLineLabel(ByVal c As XYChart, ByVal mouseX As Integer)

        ' Clear the current dynamic layer and get the DrawArea object to draw on it.
        Dim d As DrawArea = c.initDynamicLayer()

        ' The plot area object
        Dim plotArea As PlotArea = c.getPlotArea()

        ' Get the data x-value that is nearest to the mouse, and find its pixel coordinate.
        Dim xValue As Double = c.getNearestXValue(mouseX)
        Dim xCoor As Integer = c.getXCoor(xValue)

        ' Draw a vertical track line at the x-position
        d.vline(plotArea.getTopY(), plotArea.getBottomY(), xCoor, d.dashLineColor(&H0, &H101))

        ' Draw a label on the x-axis to show the track line position.
        Dim xlabel As String = "<*font,bgColor=000000*> " & c.xAxis().getFormattedLabel(xValue, _
            "mmm dd, yyyy") & " <*/font*>"
        Dim t As TTFText = d.text(xlabel, "Arial Bold", 8)

        ' Restrict the x-pixel position of the label to make sure it stays inside the chart image.
        Dim xLabelPos As Integer = Math.Max(0, Math.Min(xCoor - t.getWidth() / 2, c.getWidth() - t.getWidth( _
            )))
        t.draw(xLabelPos, plotArea.getBottomY() + 6, &HFFFFFF)

        ' Iterate through all layers to draw the data labels
        For i As Integer = 0 To c.getLayerCount() - 1
            Dim layer As Layer = c.getLayerByZ(i)

            ' The data array index of the x-value
            Dim xIndex As Integer = layer.getXIndexOf(xValue)

            ' Iterate through all the data sets in the layer
            For j As Integer = 0 To layer.getDataSetCount() - 1
                Dim dataSet As ChartDirector.DataSet = layer.getDataSetByZ(j)

                ' Get the color and position of the data label
                Dim color As Integer = dataSet.getDataColor()
                Dim yCoor As Integer = c.getYCoor(dataSet.getPosition(xIndex), dataSet.getUseYAxis())

                ' Draw a track dot with a label next to it for visible data points in the plot area
                If (yCoor >= plotArea.getTopY()) And (yCoor <= plotArea.getBottomY()) And (color <> _
                    Chart.Transparent) And (Not String.IsNullOrEmpty(dataSet.getDataName())) Then

                    d.circle(xCoor, yCoor, 4, 4, color, color)

                    Dim label As String = "<*font,bgColor=" & Hex(color) & "*> " & c.formatValue( _
                        dataSet.getValue(xIndex), "{value|P4}") & " <*/font*>"
                    t = d.text(label, "Arial Bold", 8)

                    ' Draw the label on the right side of the dot if the mouse is on the left side the chart,
                    ' and vice versa. This ensures the label will not go outside the chart image.
                    If xCoor <= (plotArea.getLeftX() + plotArea.getRightX()) / 2 Then
                        t.draw(xCoor + 5, yCoor, &HFFFFFF, Chart.Left)
                    Else
                        t.draw(xCoor - 5, yCoor, &HFFFFFF, Chart.Right)
                    End If
                End If
            Next
        Next

    End Sub

    Private Sub chartUpdateTimer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chartUpdateTimer.Tick
        winChartViewer1.updateViewPort(True, False)
    End Sub
    Private Sub dataRateTimer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles dataRateTimer.Tick

        Do While nextDataTime < DateTime.Now
            '
            ' In this demo, we use some formulas to generate new values. In real applications,
            ' it may be replaced by some data acquisition code.
            '
            Dim p As Double = nextDataTime.Ticks / 10000000.0 * 4
            Dim dataA As Double = 20 + Math.Cos(p * 2.2) * 10 + 1 / (Math.Cos(p) * Math.Cos(p) + 0.01)
            Dim dataB As Double = 150 + 100 * Math.Sin(p / 27.7) * Math.Sin(p / 10.1)
            Dim dataC As Double = 150 + 100 * Math.Cos(p / 6.7) * Math.Cos(p / 11.9)

            ' We provide some visual feedback to the numbers generated, so you can see the
            ' values being generated.
            valueA.Text = dataA.ToString(".##")
            valueB.Text = dataB.ToString(".##")
            valueC.Text = dataC.ToString(".##")

            ' After obtaining the new values, we need to update the data arrays.
            If currentIndex < timeStamps.Length Then
                ' Store the new values in the current index position, and increment the index.
                dataSeriesA(currentIndex) = dataA
                dataSeriesB(currentIndex) = dataB
                dataSeriesC(currentIndex) = dataC
                timeStamps(currentIndex) = nextDataTime
                currentIndex += 1
            Else
                ' The data arrays are full. Shift the arrays and store the values at the end.
                shiftData(dataSeriesA, dataA)
                shiftData(dataSeriesB, dataB)
                shiftData(dataSeriesC, dataC)
                shiftData(timeStamps, nextDataTime)
            End If

            ' Update nextDataTime. This is needed by our data generator. In real applications,
            ' you may not need this variable or the associated do/while loop.
            nextDataTime = nextDataTime.AddMilliseconds(dataRateTimer.Interval)
        Loop
        winChartViewer1.updateViewPort(True, False)
    End Sub


    '
    ' Utility to shift a value into an array
    '
    Private Sub shiftData(ByVal data As Object, ByVal newValue As Object)

        Dim i As Integer
        For i = 1 To UBound(data)
            data(i - 1) = data(i)
        Next
        data(UBound(data)) = newValue

    End Sub

    '
    ' Draw the track line with legend
    '
    Private Sub trackLineLegend(ByVal c As XYChart, ByVal mouseX As Integer)

        ' Clear the current dynamic layer and get the DrawArea object to draw on it.
        Dim d As DrawArea = c.initDynamicLayer()

        ' The plot area object
        Dim plotArea As PlotArea = c.getPlotArea()

        ' Get the data x-value that is nearest to the mouse, and find its pixel coordinate.
        Dim xValue As Double = c.getNearestXValue(mouseX)
        Dim xCoor As Integer = c.getXCoor(xValue)

        ' Draw a vertical track line at the x-position
        d.vline(plotArea.getTopY(), plotArea.getBottomY(), xCoor, d.dashLineColor(&H0, &H101))

        ' Container to hold the legend entries
        Dim legendEntries As ArrayList = New ArrayList()

        ' Iterate through all layers to build the legend array
        For i As Integer = 0 To c.getLayerCount() - 1
            Dim layer As Layer = c.getLayerByZ(i)

            ' The data array index of the x-value
            Dim xIndex As Integer = layer.getXIndexOf(xValue)

            ' Iterate through all the data sets in the layer
            For j As Integer = 0 To layer.getDataSetCount() - 1
                Dim dataSet As ChartDirector.DataSet = layer.getDataSetByZ(j)

                ' We are only interested in visible data sets with names
                Dim dataName As String = dataSet.getDataName()
                Dim color As Integer = dataSet.getDataColor()
                If (Not String.IsNullOrEmpty(dataName)) And (color <> Chart.Transparent) Then
                    ' Build the legend entry, consist of the legend icon, name and data value.
                    Dim dataValue As Double = dataSet.getValue(xIndex)
                    legendEntries.Add("<*block*>" & dataSet.getLegendIcon() & " " & dataName & ": " & IIf( _
                        dataValue = Chart.NoValue, "N/A", c.formatValue(dataValue, "{value|P4}")) & "<*/*>")

                    ' Draw a track dot for data points within the plot area
                    Dim yCoor As Integer = c.getYCoor(dataSet.getPosition(xIndex), dataSet.getUseYAxis())
                    If (yCoor >= plotArea.getTopY()) And (yCoor <= plotArea.getBottomY()) Then
                        d.circle(xCoor, yCoor, 4, 4, color, color)
                    End If
                End If
            Next
        Next

        ' Create the legend by joining the legend entries
        legendEntries.Reverse()
        Dim legendText As String = "<*block,maxWidth=" & plotArea.getWidth() & _
            "*><*block*><*font=Arial Bold*>[" & c.xAxis().getFormattedLabel(xValue, "hh:nn:ss.ff") & _
            "]<*/*>        " & Join(CType(legendEntries.ToArray(GetType(String)), String()), "        ") & _
            "<*/*>"

        ' Display the legend on the top of the plot area
        Dim t As TTFText = d.text(legendText, "Arial", 8)
        t.draw(plotArea.getLeftX() + 5, plotArea.getTopY() - 3, &H0, Chart.BottomLeft)

    End Sub

    Private Sub freezePB_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles freezePB.CheckedChanged

        chartUpdateTimer.Enabled = runPB.Checked
    End Sub
End Class

  Re: Add zoom to real time chart
Posted by Hun Siong on Nov-19-2013 21:03
Dear Sir/Madam,

I am using zooming and scrolling with track line sample and integrate with the real time track line. But having issue on the zooming issue.

Please help.

Hun Siong

  Re: Add zoom to real time chart
Posted by Hun Siong on Nov-20-2013 20:23
Hi Peter,

Please help me. Urgent.

Thank You.

Best Regards,
Hun Siong

  Re: Add zoom to real time chart
Posted by Peter Kwan on Nov-21-2013 03:30
Attachments:
Hi Hun Siong,

There are many ways to add realtime chart features to a zoomable and scrollable chart. I happend to have an example written in C++/MFC. I have just ported it to VB as attached.

Hope this can help.

Regards
Peter Kwan
realtime_zoomscrolltrack2_vb.zip
realtime_zoomscrolltrack2_vb.zip

9.79 Kb

  Re: Add zoom to real time chart
Posted by Hun Siong on Nov-22-2013 11:13
Dear Peter,

It works. Thanks a lot.

Best Regards,
Hun Siong

  Re: Add zoom to real time chart
Posted by Arumugam on Mar-23-2015 16:31
Hi Peter,

Can you give same sample code for C# also with zoom & pan in all direction support.

Thanks.

  Re: Add zoom to real time chart
Posted by Peter Kwan on Mar-24-2015 03:10
Hi Arumugam,

Yes. You may download it from:

http://www.advsofteng.com/realtime_zoomscrolltrack2_csharp.zip

Hope this can help.

Regards
Peter Kwan