65.9K
CodeProject 正在变化。 阅读更多。
Home

TimeSlider - 基于时间的 TrackBar

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.35/5 (11投票s)

2006年4月6日

3分钟阅读

viewsIcon

106804

downloadIcon

3591

一个使用日期而不是整数值的自定义滑动条控件。

Sample Image

引言

一个新的工作项目涉及一个视频播放系统,能够注释视频中的关键帧和片段作为感兴趣的点。其他各方可以返回并搜索视频中的注释帧,从而能够直接跳转到关键图像,而不必浏览整个文件。

我很快就意识到,在视频下方有一个滑动条会很好,类似于 Windows Media Player 或 QuickTime 查看器。更好的是一个能够跟踪用户在视频中的位置,并可以显示关于视频开始和结束时间的关键信息。我一直都是 CodeProject 的粉丝,这很快就让我觉得有机会为我多年来窃取的所有代码做出贡献。因此,TimeSlider 控件的想法诞生了。

使用控件

TimeSlider 控件可以像任何其他 .NET 控件一样使用 - 只需将其添加到工具箱中,然后将其拖到表单上。所有属性都通过 VS.NET 中的标准属性网格公开。

TimeSlider 控件基本上是一个使用 DateTime 值而不是整数值作为输入(和输出)的滑动条控件。它基于标准的 Windows 滑动条,但 MinimumMaximumValue 等属性现在是 DateTime 值,而 SmallChangeLargeChangeTickFrequency 属性现在是 TimeSpan 值。

此外,TimeSlider 提供了一些新功能,这些功能对我来说有意义,或者是我项目特别需要的。这些是

  • 打开或关闭显示最小值、最大值和当前值的标签。标签的格式通过 FormatCustomFormat 属性定义。我还在可用的“标准”格式的数量上进行了扩展,以包括诸如 ShortDateLongTimeNoDateShortTime 之类的内容。
  • 将当前值查看为绝对的 DateTime 值或作为时间段的持续时间。
  • 如果传入的日期值大于定义的最大值,则可以自动增加最大日期值。这对于实时视频流非常有用,因为您不知道结束日期是什么。
  • 能够定义时间线中的一个感兴趣的片段,它显示为控件上的一个片段条。

使用代码

TimeSlider 控件背后的代码的大部分都非常简单,这里不值得特别注意。该控件使用 Windows TrackBar 作为其基类。在幕后,TrackBar 始终提供 0 到 100 之间的值,这些值在传递给控件之前从日期值转换而来。相反,当滑块移动时从控件馈送的整数值被转换为日期值,然后传递给容器。

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();

一个有趣的点是能够绘制到现有的 TrackBar 控件上。Windows 控件设置为执行所有绘图,在这种情况下,不会向子类化的控件发送任何 OnPaint 事件,或者不执行任何绘图,期望新控件在 OnPaint 事件期间执行所有绘图操作。

在我的例子中,我希望 TrackBar 自己绘制,但允许我在其上绘制一个片段条。为了使其工作,我必须执行一些技巧,交换 UserPaint 标志足够长的时间以说服基本控件自己绘制。

public TimeSlider() {

    ...

    // this call says "I'll draw it myself"
    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);
}

注意事项

该控件仅在水平布局模式下正确运行,并且在刻度样式设置为 BottomRight 时效果最佳。这绝对是版本 2 的候选者(如果存在足够的兴趣)。

历史

这是该控件的版本 1。请随时报告错误、问题或请求。

© . All rights reserved.