Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve tracker style (Windows Forms) #106

objorke opened this issue Aug 14, 2014 · 1 comment


Copy link

commented Aug 14, 2014

Imported from

objo 2014-02-02 20:56
Currently it is implemented as a simple label. Should be improved:

  • move it away so the mouse cursor does not obscure it
  • add padding
  • add border
  • make colors (text, border, background) customizable
  • make it possible to hide it completely?

decatf 2014-02-26 21:42
I am trying to create a better tracker for the Windows Forms control. I've posted my attempt at it:

From what I can tell the way Windows Forms controls are rendered makes it difficult to dynamically render controls on top of each other in a clean way. I looks like the parent controls are redrawn constantly as child controls are being updated or redrawn. The
current tracker is a Label control and when we show the tracker and move it around the plot control OnPaint gets called a lot.

In my approach the tracker control is overlayed on top of the plot control (with the same dimensions). It is a sibling of the plot control so it is attached to the plot's parent. The tracker control draws the plot control to a bitmap which is used as its background
(drawn in the OnPaintBackground). The actual tracker is rendered in OnPaint.

The tracker control has RefreshControl and InvalidateControl methods. I followed RefreshPlot and InvalidPlot convention to tell the tracker to update the plot control bitmap. So the refresh and invalidate methods are called in plot controls refresh/invalidate
method. These methods when passed a true argument will refresh the plot control bitmap. This way the plot control is redrawn only when necessary.

It felt a bit hacky to me but I haven't been able to find a way to render a control on top of another without having to repaint the control beneath it.

decatf 2014-06-30 23:03
I had tried this some more. I got rid of the extra control and put the bitmap buffer in the plot control iteslf. It was all pointless anyways because Graphics.DrawImage does not scale at all. The larger the bitmap gets the worse the performance of that
call is. It just slows and slow whole number multiples of milliseconds per render as the size increases.

The author of Paint.Net mentioned it while ago.

decatf 2014-07-03 19:41
I was looking in the wrong place to do this. There is a GraphicsBuffer class which can be used instead of Bitmap. In this approach the plot model is rendered to a GraphicsBuffer. In the PlotView OnPaint event the buffer is rendered to the control by doing
GraphicsBuffer.Render(e.Graphics). The tracker (TrackerView) is a child control over the plot view.

I did some performance test using the "LineSeries, 100k points" series. I measured the OnPaint time of using the current (default) way of rendering versus using BufferedGraphics. The test were done at two plot sizes 650x325 and 1886x1111 (maximized
window). The first section below is the performance of just doing Model.Invalidate(true). There is some but less than 1ms overhead to render the model again and flip buffer to the control. The overhead depends on the size of the area.

In the second section the tracker control is shown and the model is rendered from buffer. It is much faster to do it with buffered graphics since the model is not being rendered each time. I recorded the paint time of the plot view and tracker view then sum
them sup. It is up to ten times faster to not unnecessarily to render the model on each paint event.

The third section the test performs worst case where everything is rendered again. The model is invalidated so there is a new render of the plot model to the buffer. The tracker is also shown. In this worst case where everything is rendered it is ~0.3000ms
to ~0.8000ms slower depending on the resolution.

Invalidate and render the plot model:

Times measured in milliseconds.

         650x325  1886x1111  
default: 2.8915 4.4068
default: 2.8621 4.3437
default: 2.8847 4.3612
default: 2.9536 4.4434
default: 2.8494 4.4261

                  650x325  1886x1111  
BufferedGraphics: 2.9595 4.8379
BufferedGraphics: 2.9405 4.8489
BufferedGraphics: 3.0002 4.8983
BufferedGraphics: 2.9746 4.9208
BufferedGraphics: 3.2227 5.2195

Show the tracker and render the plot model from buffer:

PlotView.OnPaint time:
         650x325  1886x1111      
default: 2.3262 3.8792
default: 2.3162 3.8837
default: 2.2809 3.8721
default: 2.2712 3.8262
default: 2.3161 3.9065

Graphics buffer time (Res 650x325):
                  PlotView.OnPaint  TrackerView.OnPaint  Sum
BufferedGraphics: 0.0257            0.0775               0.1032
BufferedGraphics: 0.0257            0.0795               0.1052
BufferedGraphics: 0.0255            0.0770               0.1025
BufferedGraphics: 0.0256            0.0764               0.1020
BufferedGraphics: 0.0238            0.0764               0.1002

Graphics buffer time (Res 1886x1111):
                  PlotView.OnPaint  TrackerView.OnPaint  Sum
BufferedGraphics: 0.2864            0.0933               0.3797
BufferedGraphics: 0.2909            0.0879               0.3788
BufferedGraphics: 0.2896            0.0868               0.3764
BufferedGraphics: 0.2866            0.0831               0.3697
BufferedGraphics: 0.2908            0.0870               0.3778

Show the tracker and re-render the plot model:

PlotView.OnPaint time:
         650x325  1886x1111 
default: 2.9368 4.4725
default: 2.9123 4.4976
default: 2.8252 4.4693
default: 2.9099 4.4802
default: 2.8921 4.4573

Graphics buffer time (Res 650x325):
                  PlotView.OnPaint  TrackerView.OnPaint  Sum
BufferedGraphics: 2.9239            0.0738               2.9977
BufferedGraphics: 2.9909            0.0737               3.0646
BufferedGraphics: 3.0033            0.0740               3.0773
BufferedGraphics: 2.9785            0.0739               3.0524
BufferedGraphics: 3.0049            0.0738               3.0787

Graphics buffer time (Res 1886x1111):
                  PlotView.OnPaint  TrackerView.OnPaint  Sum
BufferedGraphics: 4.8823            0.0802               4.9625
BufferedGraphics: 4.9195            0.0802               4.9997
BufferedGraphics: 4.9853            0.0806               5.0659
BufferedGraphics: 4.9327            0.0804               5.0131
BufferedGraphics: 5.0101            0.0807               5.0908

decatf 2014-07-10 21:43
Any feedback?

objo 2014-07-11 22:06
Great work! I need some time to ´digest` and test this. And I will be mostly offline the next 3 weeks. Can anybody else using WinForms give their input?

@tibel tibel added the Windows Forms label May 7, 2015
@objorke objorke removed the CodePlex label Oct 4, 2015

This comment has been minimized.

Copy link

commented Mar 1, 2016

It would be nice to have this feature. Also, currently if tracker position is at rightmost position inside the plot it's overlapped by plot bounds and not fully displayed.

@objorke objorke added the you-take-it label Mar 1, 2016
linquize added a commit to linquize/oxyplot that referenced this issue Apr 15, 2016
@linquize linquize referenced this issue Apr 15, 2016
2 of 2 tasks complete
@tibel tibel closed this in #856 Apr 19, 2016
tibel added a commit that referenced this issue Apr 19, 2016
Improve tracker style (Windows Forms) (#106)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
3 participants
You can’t perform that action at this time.