毫秒级别计时器扩展----------WinForm控件开发系列

Posted tlmbem

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了毫秒级别计时器扩展----------WinForm控件开发系列相关的知识,希望对你有一定的参考价值。

技术图片

该控件是继承于 Component 基类开发的。主要是利用 winmm.dll  的 timeGetDevCaps  、timeSetEvent  、 timeKillEvent 来完成。

  1     /// <summary>
  2     /// 毫秒级别计时器扩展
  3     /// </summary>
  4     [ToolboxItem(true)]
  5     [Description("毫秒级别计时器扩展")]
  6     [DefaultProperty("Interval")]
  7     [DefaultEvent("Tick")]
  8     public partial class TimerExt : Component
  9     {
 10         #region 新增事件
 11 
 12         private event EventHandler tick;
 13         /// <summary>
 14         /// 计时器间隔引发事件
 15         /// </summary>
 16         public event EventHandler Tick
 17         {
 18             add { this.tick += value; }
 19             remove { this.tick -= value; }
 20         }
 21 
 22         #endregion
 23 
 24         #region 新增属性
 25 
 26         private uint interval = 10;
 27         /// <summary>
 28         ///   获取或设置在相对于上一次发生的Tick 事件引发的时间(以毫秒为单位)。
 29         /// </summary>
 30         [DefaultValue(10)]
 31         [Description("获取或设置在相对于上一次发生的Tick 事件引发的时间(以毫秒为单位)。")]
 32         public uint Interval
 33         {
 34             get
 35             {
 36                 return this.interval;
 37             }
 38             set
 39             {
 40                 if (this.interval == value || value < timecaps.wPeriodMin || value > timecaps.wPeriodMax)
 41                     return;
 42 
 43                 this.interval = value;
 44 
 45                 if (this.Enabled)
 46                 {
 47                     this.ReStart();
 48                 }
 49             }
 50         }
 51 
 52         private bool enabled = false;
 53         /// <summary>
 54         /// 获取或设置计时器是否正在运行。
 55         /// </summary>
 56         [DefaultValue(false)]
 57         [Description("获取或设置计时器是否正在运行。")]
 58         public bool Enabled
 59         {
 60             get
 61             {
 62                 return this.enabled;
 63             }
 64             set
 65             {
 66                 if (this.enabled == value)
 67                     return;
 68 
 69                 if (this.enabled == false)
 70                 {
 71                     this.Start();
 72                 }
 73                 else
 74                 {
 75                     this.Stop();
 76                 }
 77                 this.enabled = value;
 78             }
 79         }
 80 
 81         /// <summary>
 82         /// 计时器分辨率的信息
 83         /// </summary>
 84         [Description("计时器分辨率的信息")]
 85         public TIMECAPS Timecaps
 86         {
 87             get { return TimerExt.timecaps; }
 88         }
 89 
 90         #endregion
 91 
 92         #region 字段
 93 
 94         /// <summary>
 95         /// 计时器分辨率的信息
 96         /// </summary>
 97         private static TIMECAPS timecaps;
 98 
 99         /// <summary>
100         ///作为fptc参数的函数指针
101         /// </summary>
102         private TimerExtCallback timerExtCallback;
103 
104         /// <summary>
105         /// 定期是标识
106         /// </summary>
107         private uint timerID;
108 
109         #endregion
110 
111         #region  扩展
112 
113         private delegate void TimerExtCallback(uint uTimerID, uint uMsg, uint dwUser, UIntPtr dw1, UIntPtr dw2); // timeSetEvent所对应的回调函数的签名
114 
115         /// <summary>
116         /// 查询计时器设备以确定其分辨率成功
117         /// </summary>
118         private const int TIMERR_NOERROR = 0x0000;
119 
120         /// <summary>
121         /// 当计时器到期时,系统将调用fptc参数指向的函数。
122         /// </summary>
123         private const int TIME_CALLBACK_FUNCTION = 0x0001;
124 
125         /// <summary>
126         /// 此结构包含有关计时器分辨率的信息。单位是ms
127         /// </summary>
128         [Description("此结构包含有关计时器分辨率的信息。单位是ms")]
129         [StructLayout(LayoutKind.Sequential)]
130         public struct TIMECAPS
131         {
132             /// <summary>
133             /// 支持的最小期限。
134             /// </summary>
135             [Description("支持的最小期限")]
136             public uint wPeriodMin;
137             /// <summary>
138             /// 支持的最大期限。
139             /// </summary>
140             [Description("支持的最大期限")]
141             public uint wPeriodMax;
142         }
143 
144         /// <summary>
145         /// 此函数启动指定的计时器事件。
146         /// </summary>
147         /// <param name="uDelay">事件延迟,以毫秒为单位。如果该值不在计时器支持的最小和最大事件延迟范围内,则该函数返回错误。</param>
148         /// <param name="uResolution">计时器事件的分辨率,以毫秒为单位。分辨率越高,分辨率越高;零分辨率表示周期性事件应该以最大可能的精度发生。但是,为减少系统开销,应使用适合您的应用程序的最大值。</param>
149         /// <param name="fptc">如果fuEvent指定TIME_CALLBACK_EVENT_SET或TIME_CALLBACK_EVENT_PULSE标志,则fptc参数将解释为事件对象的句柄。事件将在单个事件完成时设置或发出脉冲,或者在周期性事件完成时定期设置或触发。对于fuEvent的任何其他值,fptc参数将被解释为函数指针。</param>
150         /// <param name="dwUser">用户提供的回调数据。</param>
151         /// <param name="fuEvent">计时器事件类型。下表显示了fuEvent参数可以包含的值。</param>
152         /// <returns></returns>
153         [DllImport("winmm.dll")]
154         private static extern uint timeSetEvent(uint uDelay, uint uResolution, TimerExtCallback fptc, uint dwUser, uint fuEvent);
155 
156         /// <summary>
157         /// 此功能取消指定的计时器事件。
158         /// </summary>
159         /// <param name="id">要取消的计时器事件的标识符。此标识符由timeSetEvent函数返回,该函数启动指定的计时器事件。</param>
160         /// <returns></returns>
161         [DllImport("winmm.dll")]
162         private static extern uint timeKillEvent(uint uTimerID);
163 
164         /// <summary>
165         /// 此函数查询计时器设备以确定其分辨率。
166         /// </summary>
167         /// <param name="ptc">指向TIMECAPS结构的指针。该结构充满了有关计时器设备分辨率的信息。</param>
168         /// <param name="cbtc">TIMECAPS结构的大小(以字节为单位)。</param>
169         /// <returns>如果成功,则返回TIMERR_NOERROR,如果未能返回计时器设备功能,则返回TIMERR_STRUCT。</returns>
170         [DllImport("winmm.dll")]
171         private static extern uint timeGetDevCaps(ref TIMECAPS ptc, int cbtc);
172 
173         #endregion
174 
175         static TimerExt()
176         {
177             uint result = timeGetDevCaps(ref timecaps, Marshal.SizeOf(timecaps));
178             if (result != TIMERR_NOERROR)
179             {
180                 throw new Exception("timeGetDevCaps失败");
181             }
182         }
183 
184         public TimerExt()
185         {
186             this.timerExtCallback = new TimerExtCallback(this.TimerExtCallbackFun);
187             InitializeComponent();
188         }
189 
190         public TimerExt(IContainer container)
191         {
192             this.timerExtCallback = new TimerExtCallback(this.TimerExtCallbackFun);
193 
194             container.Add(this);
195             InitializeComponent();
196         }
197 
198         #region 重写
199 
200         /// <summary> 
201         /// 清理所有正在使用的资源。
202         /// </summary>
203         /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
204         protected override void Dispose(bool disposing)
205         {
206             if (disposing && (components != null))
207             {
208                 components.Dispose();
209             }
210 
211             if (this.timerID != 0)
212             {
213                 timeKillEvent(this.timerID);
214                 this.timerID = 0;
215             }
216             base.Dispose(disposing);
217         }
218 
219         #endregion
220 
221         #region 公开方法
222 
223         /// <summary>
224         /// 启动定时器
225         /// </summary>
226         public void Start()
227         {
228             if (!this.Enabled)
229             {
230                 uint result = timeSetEvent(this.interval, Math.Min(1, timecaps.wPeriodMin), this.timerExtCallback, 0, TIME_CALLBACK_FUNCTION); // 间隔性地运行
231                 if (result == 0)
232                 {
233                     throw new Exception("timeSetEvent启动计时器失败");
234                 }
235                 this.enabled = true;
236                 this.timerID = result;
237             }
238         }
239 
240         /// <summary>
241         /// 重新开始定时器
242         /// </summary>
243         public void ReStart()
244         {
245             this.Stop();
246             this.Start();
247         }
248 
249         /// <summary>
250         /// 暂停定时器
251         /// </summary>
252         public void Stop()
253         {
254             if (this.Enabled)
255             {
256                 timeKillEvent(this.timerID);
257                 this.enabled = false;
258             }
259         }
260 
261         #endregion
262 
263         #region 私有方法
264 
265         private void TimerExtCallbackFun(uint uTimerID, uint uMsg, uint dwUser, UIntPtr dw1, UIntPtr dw2)
266         {
267             if (this.tick != null)
268             {
269                 this.tick(this, null);
270             }
271         }
272 
273         #endregion
274 
275     }

源码下载:毫秒级别计时器扩展.zip

以上是关于毫秒级别计时器扩展----------WinForm控件开发系列的主要内容,如果未能解决你的问题,请参考以下文章

毫秒,微妙级别软件定时器

在SysTick微秒及毫秒程序举例中,定时器一次最大定时时间是多少毫秒?

iOS 毫秒倒计时列表

swoole定时器

c#中怎样建立定时器?用以替代thread.sleep(),克服sleep延时不精确的问题。

VB定时器控件Interval属性设置为0是啥意思?