毫秒級別計時器擴展----------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     }

控件庫的源碼已整體發布到gitee,下載地址:(花木蘭控件庫)https://gitee.com/tlmbem/hml


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM