Home Forums WinForms controls Xceed Chart for WinForms How to make a small window follow the cursor on a chart

Viewing 3 posts - 1 through 3 (of 3 total)
  • Author
    Posts
  • User (Old forums)
    Member
    Post count: 23064
    #19164 |

    I have an app that displays spectrograph charts – the X axis is frequency (typically in megahertz), the Y axis is amplitude (typically in dB). Sometimes the X axis is logarithmic, sometimes numeric.  What I want is to display the frequency and amplitude value next to the cursor as the mouse is rolled over the chart.  I have it nearly working, but I cannot get it to position consistently – the result I get seems to vary depending on the axis scales. I got it all working OK on a chart with numerix X-axis, and thought I was done, but then it didn’t quite work on one with a logarithmic X-axis.

    I am using the OnDataCursorChange event to do this. I have a small window with a transparent background and 2 labels to contain the values.  In the OnDataCursorChange event, I do the following:

    1. Get the min and max values for the X and Y axes.  If the cursor is outside these limits I don’t want the values to show, so I hide the small window.
    2. If the scale values in the DataCursorEventArgs object are within axis limits, I use ConvertScaleToModelCoordinate to convert the X and Y values to model coordinates.  I then use ConvertModelToClientCoordinate to get client coordinates, and adjust slightly so that the window appears just above and to the right of the cursor.  I have also tried using ConvertModelToViewport, but could see little or no difference in the result. I also get the model and client coordinate of the top of the Y axis, because I seemed to have to add that on to position the window properly in the Y direction.

    My questions are:
    1. Am I re-inventing a wheel here? Does the chart object already have something that will do this?
    2. The difference between client coordinates and viewport coordinates is not clear to me – the documentation is not helpful. Can someone clarify?
    4. What do I need to do to get a consistent location next to the cursor? Clearly I have something not right.

    Please note I am using a fairly old version of the chart – 4.0.100.0

    This is the code for the OnDataCursorChange event. fFollower is the instance of the small window that displays the Freq and Amplitude. It is declared at form scope level.

        Private Sub OnDataCursorChange(ByVal sender As Object, ByVal eventargs As EventArgs)

            Dim Xval As Double, Yval As Double
            Dim Xmin As Double, Xmax As Double, Ymin As Double, Ymax As Double
            Dim sText As String
            Dim dcea As DataCusorToolEventArgs = CType(eventargs, DataCusorToolEventArgs)
            Dim vcModel As New Vector, vcClient As New Vector, vcChartTop As New Vector

            ‘ Get the axis bounds
            With chtGraph.Charts(0)
                If .Axis(StandardAxis.PrimaryY).ScaleMode = AxisScaleMode.Logarithmic Then
                Else ‘ Y axis always numeric
                    Ymin = chtGraph.Charts(0).Axis(StandardAxis.PrimaryY).NumericScale.Min
                    Ymax = chtGraph.Charts(0).Axis(StandardAxis.PrimaryY).NumericScale.Max
                End If
                If .Axis(StandardAxis.PrimaryX).ScaleMode = AxisScaleMode.Logarithmic Then
                    Xmin = chtGraph.Charts(0).Axis(StandardAxis.PrimaryX).LogarithmicScale.Min
                    Xmax = chtGraph.Charts(0).Axis(StandardAxis.PrimaryX).LogarithmicScale.Max
                Else
                    Xmin = chtGraph.Charts(0).Axis(StandardAxis.PrimaryX).NumericScale.Min
                    Xmax = chtGraph.Charts(0).Axis(StandardAxis.PrimaryX).NumericScale.Max
                End If

                Xval = dcea.HorizontalAxisValue
                Yval = dcea.VerticalAxisValue
                If Xval >= Xmin And Xval <= Xmax And Yval >= Ymin And Yval <= Ymax Then
                    vcModel.x = .Axis(StandardAxis.PrimaryX).ConvertScaleToModelCoordinate(False, Xval)
                    vcModel.y = .Axis(StandardAxis.PrimaryY).ConvertScaleToModelCoordinate(False, Yval)
                    .ConvertModelToClientCoordinate(vcModel, vcClient)
                    ‘ Get the client coord of the top of the plot space (Ymax)
                    vcModel.y = .Axis(StandardAxis.PrimaryY).ConvertScaleToModelCoordinate(False, Ymax)
                    .ConvertModelToClientCoordinate(vcModel, vcChartTop)

                    fFollower.Top = vcClient.y + vcChartTop.y – 5
                    ‘ Make sure the small window doesn’t go off the right side of the chart window
                    If (vcClient.x + fFollower.Width + 10) > Me.Right Then
                        fFollower.Left = Me.Right – fFollower.Width
                    Else
                        fFollower.Left = vcClient.x + 10
                    End If
                    Cursor = Cursors.Cross
                    fFollower.lblFrequency.Text = “Frq: ” & gFormatFrequency(Xval)
                    fFollower.lblAmplitude.Text = “Amp: ” & Yval.ToString(“#0.00”)
                    If Not fFollower.Visible Then fFollower.Show()
                Else
                    fFollower.Hide()
                    Cursor = Cursors.Default
                End If
            End With

        End Sub
     

    Imported from legacy forums. Posted by Steve (had 2015 views)

    User (Old forums)
    Member
    Post count: 23064

    Further information – my app is an MDI application, and it is the MDI child windows that contain the charts.  As each child window opens, it is a little lower and further to the right than the preceding one.  This gave me the clue – if I move the child windows back to the top left of the space in the MDI parent window, everything is fine, i.e. my floating display is now where I want it to be.  This implies that the ConvertModelToClientCoordinate method is calculating coordinates relative to the MDI parent, not to the MDI child window which contains the chart.  Can that be right?  All the code above is definitely in the child window, so how this could be happening is beyond me.  But it definitely seems to be the problem – the final coordinates are relative to the MDI parent window, not the child window. Help!

    Imported from legacy forums. Posted by Steve (had 278 views)

    User (Old forums)
    Member
    Post count: 23064

    So, I have solved my own problem.  I simply have to offset the coordinates I calculate by the Left and Top coordinates of the MDI child window containing the chart, and it all comes right.  Trivial once known, but not what I would have expected.

    Imported from legacy forums. Posted by Steve (had 1978 views)

Viewing 3 posts - 1 through 3 (of 3 total)
  • You must be logged in to reply to this topic.