User (Old forums)MemberJanuary 20, 2010 at 4:21 amPost count: 23064
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 – 18.104.22.168
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
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
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
Xmin = chtGraph.Charts(0).Axis(StandardAxis.PrimaryX).NumericScale.Min
Xmax = chtGraph.Charts(0).Axis(StandardAxis.PrimaryX).NumericScale.Max
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)
‘ Get the client coord of the top of the plot space (Ymax)
vcModel.y = .Axis(StandardAxis.PrimaryY).ConvertScaleToModelCoordinate(False, Ymax)
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
fFollower.Left = vcClient.x + 10
Cursor = Cursors.Cross
fFollower.lblFrequency.Text = “Frq: ” & gFormatFrequency(Xval)
fFollower.lblAmplitude.Text = “Amp: ” & Yval.ToString(“#0.00”)
If Not fFollower.Visible Then fFollower.Show()
Cursor = Cursors.Default
Imported from legacy forums. Posted by Steve (had 2015 views)User (Old forums)MemberJanuary 20, 2010 at 5:28 amPost 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)MemberJanuary 20, 2010 at 7:22 amPost 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)
- You must be logged in to reply to this topic.