2021年3月16日星期二

C# 自定义时间进度条

这篇文章对我帮助极大,我模仿着写了两遍大概摸清楚了自定义控件的流程。https://www.cnblogs.com/lesliexin/p/13265707.html 感谢大佬 leslie_xin

样式

最开始

进度条有更改

根据开始时间和结束时间 时间刻度间隔有更改

设置项

正文

首先,我模仿过leslie_xin,写过一个进度条,用于播放视频,但是没有刻度,现在没有刻度不行,所以要搞一个刻度,计划使用GDI+
然后,发现https://www.cnblogs.com/lesliexin/p/13265707.html 这个控件里的长、宽不能修改,不然得自己再计算细节性得问题,就打算继承UserControl,把leslie_xin的进度条拖放进来
```UserControl```就把他当成正常窗口写,改写啥就写啥

正经脸

首先,能够满足自定以的进度条样式吧,比如前景色、背景色、进度的颜色,所以有了
  private Color _BarBackColor = Color.FromArgb(128, 255, 128);  [Category("TimeTrackBarControl"), Description("进度条背景色")]  public Color BarBackColor  {   get   {    return this.trackBar.BarBackColor;   }   set   {    _BarBackColor = value;    this.trackBar.BarBackColor = _BarBackColor;    Invalidate();   }  }  private Color _BarSliderColor = Color.FromArgb(64, 128, 64);  [Category("TimeTrackBarControl"), Description("进度条滑块颜色\r\n有值部分的颜色")]  public Color BarSliderColor  {   get   {    return this.trackBar.SliderColor;   }   set   {    _BarSliderColor = value;    this.trackBar.SliderColor = _BarSliderColor;    Invalidate();   }  }
然后因为要显示时间、开始时间、结束时间,所以又有了
  private DateTime _StartTime = DateTime.Now.AddHours(-1);  [Category("TimeTrackBarControl"), Description("开始时间")]  public DateTime StartTime  {   get   {    return _StartTime;   }   set   {    _StartTime = value;    //if (_StartTime > _EndTime) _StartTime = _EndTime.AddMinutes(-1);    _BarMaximum = (_EndTime - _StartTime).TotalSeconds.ToInt();    this.trackBar.Maximum = _BarMaximum;    this.trackBar.Minimum = 0;    Invalidate();   }  }  private DateTime _EndTime = DateTime.Now;  [Category("TimeTrackBarControl"), Description("结束时间")]  public DateTime EndTime  {   get   {    return _EndTime;   }   set   {    _EndTime = value;    //if (_EndTime < _StartTime) _EndTime = _StartTime.AddMinutes(1);    _BarMaximum = (_EndTime - _StartTime).TotalSeconds.ToInt();    this.trackBar.Maximum = _BarMaximum;    this.trackBar.Minimum = 0;    Invalidate();   }  }
再次因为要纪录进度条的值、最大值、最小值为0,记个der~,(我也不知道为啥会有这样值,脑子可能有它自己的想法)所以还有
  private int _BarMaximum = 0;  [Category("TimeTrackBarControl"), Description("最大值\r\n默认:0,由开始时间和结束时间决定(只读)")]  public int BarMaximum  {   get   {    return _BarMaximum;   }  }  private int _BarCurValue = 0;  [Category("TimeTrackBarControl"), Description("当前值")]  public int BarCurValue  {   get   {    _BarCurValue = this.trackBar.CurValue;    return _BarCurValue;   }   set   {    _BarCurValue = value;    if (_BarCurValue < 0) _BarCurValue = 0;    if (_BarCurValue > _BarMaximum) _BarCurValue = _BarMaximum;    this.trackBar.CurValue = _BarCurValue;    BarCurValueChanged?.Invoke(this, new CurValueEventArgs(_BarCurValue));   }  }
你这个时间刻度总得有颜色吧,总不能是皇帝的时间刻度,进度条的值对应的时间label也得有样式吧,皇帝也没有label啊,所以双有了
  private Color _TimeScaleColor = Color.FromArgb(210, 210, 210);  [Category("TimeTrackBarControl"), Description("时间刻度的颜色")]  public Color TimeScaleColor  {   get   {    return _TimeScaleColor;   }   set   {    _TimeScaleColor = value;    Invalidate();   }  }  private int _ScaleInterval = 1200;  [Category("TimeTrackBarControl"), Description("时间刻度之间相隔秒数,小于零表示自适应\r\n单位:秒")]  public int ScaleInterval  {   get   {    return _ScaleInterval;   }   set   {    _ScaleInterval = value;    //if (_ScaleInterval <= 0)    //{    // _ScaleInterval = 1800;    //}    Invalidate();   }  }  private int _RealScaleInterval = 1200;  [Category("TimeTrackBarControl"), Description("实际相隔的秒数(为了显示自适应时真实的间隔时间)\r\n单位:秒")]  public int RealScaleInterval  {   get   {    _RealScaleInterval = _ScaleInterval > 0 ? _ScaleInterval : _RealScaleInterval;    return _RealScaleInterval;   }  }  private Color _TimeLabelBackColor = Color.FromArgb(255, 192, 192);  [Category("TimeTrackBarControl"), Description("时间label背景色")]  public Color TimeLabelBackColor  {   get   {    return _TimeLabelBackColor;   }   set   {    _TimeLabelBackColor = value;    Invalidate();   }  }  private Color _TimeLabelForeColor = Color.FromArgb(192,255,192);  [Category("TimeTrackBarControl"), Description("时间label前景色")]  public Color TimeLabelForeColor  {   get   {    return _TimeLabelForeColor;   }   set   {    _TimeLabelForeColor = value;    Invalidate();   }  }
最后你这个时间刻度总得能够直接跳到某个时间点吧,所以叒有
  public void SeekByTime(DateTime time)  {   BarCurValue = (time - StartTime).TotalSeconds.ToInt();  }
你搞了那么多样式,总得有人去画吧,所以叕有了
  protected override void OnPaint(PaintEventArgs e)  {   base.OnPaint(e);  }
时间刻度呢?总得去生成吧,所以我们要计算一下,每个刻度之间间隔多少秒钟,毕竟进度条的最小值为零,最大值为开始时间和最小时间间隔的秒数。
所以:1、计算间隔
2、计算时间刻度的坐标
3、画出来
  /// <summary>  /// 微软雅黑 regular 10F 23:56分约占38个像素,现定为45个像素为最小值,时间刻度:60秒为最小值  /// </summary>  /// <returns></returns>  private int SelfAdaption()  {   float radio = 45 * 1.0f / trackBar.Width;//45个像素占进度条总长的比例   double interval = (_EndTime - _StartTime).TotalSeconds * radio;//这个比例下,占多长的时间   if (interval<=60)   {    interval = 60;   }   else if (interval>60 && interval <= 300)   {    interval = 300;   }   else if (interval >300 && interval <= 600)   {    interval = 600;   }   else if (interval >600 && interval <= 1200)   {    interval = 1200;   }   else if (interval > 1200 && interval <= 1800)   {    interval = 1800;   }   else if (interval > 1800 && interval <= 3600)   {    interval = 3600;   }   return Convert.ToInt32(interval);  }  /// <summary>  /// 要划线的坐标  /// </summary>  /// <param name="intervalSec"></param>  /// <returns></returns>  private List<TimeScaleLocation> TimeScaleList()  {   DateTime time = _StartTime;   if (_ScaleInterval<0)   {    _RealScaleInterval = SelfAdaption();   }   else   {    _RealScaleInterval = _ScaleInterval;   }   List<TimeScaleLocation> scales = new List<TimeScaleLocation>();   TimeScaleLocation start_scale = new TimeScaleLocation(trackBar.Location.X, trackBar.Location.Y + trackBar.Height / 2, _StartTime);   scales.Add(start_scale);   while (time.AddSeconds(_RealScaleInterval) < _EndTime)   {    time = time.AddSeconds(_RealScaleInterval);    int val = (time - _StartTime).TotalSeconds.ToInt();    float radio = val * 1.0f / _BarMaximum;    int x = trackBar.Location.X + Convert.ToInt32(trackBar.Width * radio);    int y = trackBar.Location.Y;    TimeScaleLocation scale = new TimeScaleLocation(x, y, time);    scales.Add(scale);   }   int end_x = trackBar.Location.X + trackBar.Width;   int end_y = trackBar.Location.Y + trackBar.Height / 2;   TimeScaleLocation end_scale = new TimeScaleLocation(end_x, end_y, _EndTime);   scales.Add(end_scale);   return scales;  }  // 完全体的OnPaint方法  protected override void OnPaint(PaintEventArgs e)  {   base.OnPaint(e);   ChangeStyle();   e.Graphics.SmoothingMode = SmoothingMode.HighQuality;   Pen pen = new Pen(_TimeScaleColor, 1);   Brush brush = new SolidBrush(_TimeScaleColor);   Font font = new Font("微软雅黑", 10, FontStyle.Regular, GraphicsUnit.Point, (byte)134);   List<TimeScaleLocation> scales = TimeScaleList();   for (int i = 0; i < scales.Count; i++)   {    TimeScaleLocation item = scales[i];    int length = 15;    if (_RealScaleInterval * i % 3600 == 0)    {     length = length + trackBar.Height * 1;    }    if (i == 0 || i == scales.Count - 1)    {     length = (int)(length + trackBar.Height * 1.5);    }    if (i == 0)    {     item.x -= 1;    }    e.Graphics.DrawLine(pen, item.x, item.y, item.x, item.y - length);    e.Graphics.DrawString(item.time.ToString("HH:mm"), font, brush, new Point(item.x - 19, item.y - length - trackBar.Height * 2));   }  }  // 设置label样式,onpaint方法调用  private void ChangeStyle()  {   this.timeLabel.BackColor = _TimeLabelBackColor;   this.timeLabel.ForeColor = _TimeLabelForeColor;  }
是不是发现有个TimeScaleLocation不知道是啥?
using System;namespace QAQ.Controls{ /// <summary> /// 时间刻度信息 /// </summary> public class TimeScaleLocation {  /// <summary>  /// time对应在进度条上的点的x坐标  /// </summary>  public int x { get; set; }  /// <summary>  /// time对应在进度条上的点的y坐标  /// </summary>  public int y { get; set; }  /// <summary>  /// time时间点  /// </summary>  public DateTime time{get;set;}  public TimeScaleLocation(int x, int y, DateTime time)  {   this.x = x;   this.y = y;   this.time = time;  } }}
哦,我亲爱的老伙计,我好像忘记了把事件加上来了,我今天得罚我自己吃三大碗饭,治治我这个不长记性的脑子。所以这个事件我借用那个大佬的
  #region 事件,  public delegate void CurValueChangedEventHandler(object sender, CurValueEventArgs e);  /// <summary>  /// 值发生改变时引发的事件  /// </summary>  public event CurValueChangedEventHandler BarCurValueChanged;  

没有评论:

发表评论