1

I am building a Windows Forms applicaton in C# and have a TrackBar on my Form. How can I compute the (pixel) position of the tip of the tracker? I would like to draw a line from there to another point on my form. Additionally I also would like to compute the lowest and highest possible x position of the tip.

Danvil
  • 22,240
  • 19
  • 65
  • 88

1 Answers1

6

The native Windows control that is wrapped by TrackBar has an awkward restriction, you cannot get the positions for the first and last tic marks. You can however get the display rectangles for the channel and the slider. This class returns them:

using System;
using System.Windows.Forms;
using System.Drawing;
using System.Runtime.InteropServices;

class MyTrackBar : TrackBar {
  public Rectangle Slider {
    get {
      RECT rc = new RECT();
      SendMessageRect(this.Handle, TBM_GETTHUMBRECT, IntPtr.Zero, ref rc);
      return new Rectangle(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
    }
  }
  public Rectangle Channel {
    get {
      RECT rc = new RECT();
      SendMessageRect(this.Handle, TBM_GETCHANNELRECT, IntPtr.Zero, ref rc);
      return new Rectangle(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
    }
  }
  private const int TBM_GETCHANNELRECT = 0x400 + 26;
  private const int TBM_GETTHUMBRECT = 0x400 + 25;
  private struct RECT { public int left, top, right, bottom; }
  [DllImport("user32.dll", EntryPoint = "SendMessageW")]
  private static extern IntPtr SendMessageRect(IntPtr hWnd, int msg, IntPtr wp, ref RECT lp);
}

Here is a sample usage in a form, it draws a line from the first tick mark to the slider pointer:

private void myTrackBar1_ValueChanged(object sender, EventArgs e) {
  this.Invalidate();
}
protected override void  OnPaint(PaintEventArgs e) {
  var chan = this.RectangleToClient(myTrackBar1.RectangleToScreen(myTrackBar1.Channel));
  var slider = this.RectangleToClient(myTrackBar1.RectangleToScreen(myTrackBar1.Slider));
  e.Graphics.DrawLine(Pens.Black, chan.Left + slider.Width / 2, myTrackBar1.Bottom + 5,
    slider.Left + slider.Width / 2, myTrackBar1.Bottom + 5);
}
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Abandon all hope, you just cannot make this work on Mono. Create your own TrackBar control. Could be fun. Ish. – Hans Passant Apr 28 '10 at 18:31
  • *snief* So I just "hacked" a solution by taking the control dimension and an estimatino value for the padding. This at least works at this computer running this os ... – Danvil Apr 29 '10 at 12:39