Introduction
A new work project involved a video playback system, with the ability to annotate key frames and segments within the video as points of interest. Other parties could then come back and search for annotated frames within the video, thus being able to jump directly to key images rather than having to look through the entire file.
It stuck me early on that it would be nice to have a trackbar available below the video, similar to the Windows Media Player or the QuickTime viewer. Even better would be one that kept track of where within the video the user is, and could show key information about video start and end times. I am a long-time CodeProject fan, and this quickly struck me as a chance to give something back for all the code I've stolen over the years. Thus was born the idea of the TimeSlider
control.
Using the control
The TimeSlider
control can be used like any other .NET control - just add it to your toolbox and then drag it onto a form. All properties are exposed through the standard property grid within VS.NET.
The TimeSlider
control is basically a trackbar control that uses DateTime
values instead of integer values as input (and output). It is based on the standard Windows trackbar, but properties such as Minimum
, Maximum
, and Value
are now DateTime
values, while the SmallChange
, LargeChange
, and TickFrequency
properties are now TimeSpan
values.
In addition, the TimeSlider
provides some new functionality that either made sense to me or was specifically needed for my project. These are:
- Turn on or off labels that show the minimum, maximum, and the current value. The format for labels is defined through the
Format
and CustomFormat
properties. I also extended the number of available "standard" formats to include things like ShortDateLongTime
and NoDateShortTime
.
- View current values as either absolute
DateTime
values or as duration into the time period.
- Ability to auto-increment the maximum date value if the incoming date value is greater than the defined maximum. This is useful for live video feeds, where you don't know what the end date is.
- Ability to define a segment of interest within a timeline, which shows up as a segment bar on the control.
Using the code
The majority of the code behind the TimeSlider
control is pretty straightforward and not worth special note here. The control uses the Windows TrackBar
as its base class. Under the hood, the TrackBar
is always fed values between 0 and 100, which are translated from date values before being passed on to the control. In reverse fashion, integer values fed from the control when the puck is moved are translated into date values and then passed on to the container.
double nTicksMin = mdtMin.Ticks;
double nTicksMax = mdtMax.Ticks;
double d1 = ( (double)base.Value ) / 100.0;
double nTicksCur = d1 * ( nTicksMax - nTicksMin ) + nTicksMin;
mdtCur = new DateTime((long)nTicksCur);
DrawLabels();
The one point of interest is the ability to draw onto the existing TrackBar
control. The Windows controls are set up to either perform all the drawing, in which case no OnPaint
events are sent to a sub-classed control, or to do none of the drawing, expecting the new control to perform all painting operations during the OnPaint
event.
In my case, I wanted the TrackBar
to draw itself, but allow me to draw a segment bar on top. To get this working, I had to perform some trickery, swapping the UserPaint
flag just long enough to convince the base control to draw itself.
public TimeSlider() {
...
this.SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.ResizeRedraw |
ControlStyles.UserPaint, true);
...
}
protected override void OnPaint(PaintEventArgs e) {
base.SetStyle(ControlStyles.UserPaint, false);
base.Refresh();
if ( mbShowSegment ) {
mGraphics.FillRectangle(mSegmentBrush,
new Rectangle(mSegmentRect.X,
mSegmentRect.Y,
mSegmentRect.Width,
mSegmentRect.Height));
}
base.SetStyle(ControlStyles.UserPaint, true);
}
Caveats
The control only behaves properly in horizontal layout mode, and looks best with the tick style set to BottomRight
. This would definitely be a candidate for version 2 (if enough interest exists).
History
This is version 1 of this control. Please feel free to report errors, issues, or requests.