Code:
/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / fx / src / WinForms / Managed / System / WinForms / Timer.cs / 1 / Timer.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- /* */ namespace System.Windows.Forms { using System.Threading; using System.Runtime.InteropServices; using System.ComponentModel; using System.ComponentModel.Design; using System.Diagnostics; using System.Windows.Forms.Design; using System; using System.Globalization; ////// /// [ DefaultProperty("Interval"), DefaultEvent("Tick"), ToolboxItemFilter("System.Windows.Forms"), SRDescription(SR.DescriptionTimer) ] public class Timer : Component { ///Implements a Windows-based timer that raises an event at user-defined intervals. This timer is optimized for /// use in Win Forms /// applications and must be used in a window. ////// /// private int interval; ////// /// private bool enabled; ////// /// private EventHandler onTimer; ////// /// private GCHandle timerRoot; // our holder for the HWND that handles our Timer messages. // private TimerNativeWindow timerWindow; ////// /// private object userData; private object syncObj = new object(); ////// /// public Timer() : base() { interval = 100; } ///Initializes a new instance of the ////// class. /// /// public Timer(IContainer container) : this() { container.Add(this); } ///Initializes a new instance of the ///class with the specified container. [ SRCategory(SR.CatData), Localizable(false), Bindable(true), SRDescription(SR.ControlTagDescr), DefaultValue(null), TypeConverter(typeof(StringConverter)), ] public object Tag { get { return userData; } set { userData = value; } } /// /// /// [SRCategory(SR.CatBehavior), SRDescription(SR.TimerTimerDescr)] public event EventHandler Tick { add { onTimer += value; } remove { onTimer -= value; } } ///Occurs when the specified timer /// interval has elapsed and the timer is enabled. ////// /// protected override void Dispose(bool disposing) { if (disposing) { if (timerWindow != null) { timerWindow.StopTimer(); } Enabled = false; } timerWindow = null; base.Dispose(disposing); } ////// Disposes of the resources (other than memory) used by the timer. /// ////// /// [ SRCategory(SR.CatBehavior), DefaultValue(false), SRDescription(SR.TimerEnabledDescr) ] public virtual bool Enabled { get { if (timerWindow == null) { return enabled; } return timerWindow.IsTimerRunning; } set { lock(syncObj) { if (enabled != value) { enabled = value; // At runtime, enable or disable the corresponding Windows timer // if (!DesignMode) { if (value) { // create the timer window if needed. // if (timerWindow == null) { timerWindow = new TimerNativeWindow(this); } timerRoot = GCHandle.Alloc(this); timerWindow.StartTimer(interval); } else{ if (timerWindow != null){ timerWindow.StopTimer(); } if (timerRoot.IsAllocated) { timerRoot.Free(); } } } } } } } ///Indicates whether the timer is /// running. ////// /// [ SRCategory(SR.CatBehavior), DefaultValue(100), SRDescription(SR.TimerIntervalDescr) ] public int Interval { get { return interval; } set { lock(syncObj) { if (value < 1) throw new ArgumentOutOfRangeException("Interval", SR.GetString(SR.TimerInvalidInterval, value, (0).ToString(CultureInfo.CurrentCulture))); if (interval != value) { interval = value; if (Enabled) { Debug.Assert(DesignMode || timerWindow != null, "Why don't we have a timer HWND?"); // just change the timer value, don't tear down the timer // itself. // if (!DesignMode && timerWindow != null) { timerWindow.RestartTimer(value); } } } } } } ////// Indicates the time, in milliseconds, between timer ticks. ////// /// protected virtual void OnTick(EventArgs e) { if (onTimer != null) onTimer(this, e); } ///Raises the ////// event. /// /// public void Start() { Enabled = true; } ///Starts the /// timer. ////// /// public void Stop() { Enabled = false; } ///Stops the /// timer. ////// /// returns us as a string. /// ///public override string ToString() { string s = base.ToString(); return s + ", Interval: " + Interval.ToString(CultureInfo.CurrentCulture); } private class TimerNativeWindow : NativeWindow { // the timer that owns us // private Timer _owner; // our current id -- this is usally the same as TimerID but we also // use it as a flag of when our timer is running. // private int _timerID; // arbitrary timer ID. // private static int TimerID = 1; // setting this when we are stopping the timer so someone can't restart it in the process. // private bool _stoppingTimer; internal TimerNativeWindow(Timer owner) { this._owner = owner; } ~TimerNativeWindow() { // note this call will work form the finalizer thread. // StopTimer(); } public bool IsTimerRunning { get { return _timerID != 0 && Handle != IntPtr.Zero; } } // Ensures that our HWND has been created. // private bool EnsureHandle() { if (Handle == IntPtr.Zero) { // we create a totally vanilla invisible window just for WM_TIMER messages. // CreateParams cp = new CreateParams(); cp.Style = 0; cp.ExStyle = 0; cp.ClassStyle = 0; cp.Caption = GetType().Name; // Message only windows are cheaper and have fewer issues than // full blown invisible windows. But, they are only supported // on NT. if (Environment.OSVersion.Platform == PlatformID.Win32NT) { cp.Parent = (IntPtr)NativeMethods.HWND_MESSAGE; } CreateHandle(cp); } Debug.Assert(Handle != IntPtr.Zero, "Timer HWND creation failed!"); return Handle != IntPtr.Zero; } // Returns true if we need to marshal across threads to access this timer's HWND. // private bool GetInvokeRequired(IntPtr hWnd) { if (hWnd != IntPtr.Zero) { int pid; int hwndThread = SafeNativeMethods.GetWindowThreadProcessId(new HandleRef(this, hWnd), out pid); int currentThread = SafeNativeMethods.GetCurrentThreadId(); return(hwndThread != currentThread); } return false; } // change the interval of the timer without destroying the HWND. // public void RestartTimer(int newInterval) { StopTimer(false, IntPtr.Zero); StartTimer(newInterval); } // Start the timer with the specified interval. // public void StartTimer(int interval) { if (_timerID == 0 && !_stoppingTimer) { if (EnsureHandle()) { _timerID = (int) SafeNativeMethods.SetTimer(new HandleRef(this, Handle), TimerID++, interval, IntPtr.Zero); } } } // stop the timer. // public void StopTimer() { StopTimer(true, IntPtr.Zero); } // stop the timer and optionally destroy the HWND. // public void StopTimer(bool destroyHwnd, IntPtr hWnd) { if (hWnd == IntPtr.Zero) { hWnd = Handle; } // Fire a message across threads to destroy the timer and HWND on the thread that created it. // if (GetInvokeRequired(hWnd)) { UnsafeNativeMethods.PostMessage(new HandleRef(this, hWnd), NativeMethods.WM_CLOSE, 0, 0); return; } // Locking 'this' here is ok since this is an internal class. See VSW#464499. lock(this) { if (_stoppingTimer || hWnd == IntPtr.Zero || !UnsafeNativeMethods.IsWindow(new HandleRef(this, hWnd))) { return; } if (_timerID != 0) { try { _stoppingTimer = true; SafeNativeMethods.KillTimer(new HandleRef(this, hWnd), _timerID); } finally { _timerID = 0; _stoppingTimer = false; } } if (destroyHwnd) { base.DestroyHandle(); } } } // Destroy the handle, stopping the timer first. // public override void DestroyHandle() { // don't recurse! // StopTimer(false, IntPtr.Zero); Debug.Assert(_timerID == 0, "Destroying handle with timerID still set."); base.DestroyHandle(); } protected override void OnThreadException(Exception e) { Application.OnThreadException(e); } public override void ReleaseHandle() { // don't recurse! // StopTimer(false, IntPtr.Zero); Debug.Assert(_timerID == 0, "Destroying handle with timerID still set."); base.ReleaseHandle(); } protected override void WndProc(ref Message m) { Debug.Assert(m.HWnd == Handle && Handle != IntPtr.Zero, "Timer getting messages for other windows?"); // for timer messages, make sure they're ours (it'll be wierd if they aren't) // and call the timer event. // if (m.Msg == NativeMethods.WM_TIMER) { //Debug.Assert((int)m.WParam == _timerID, "Why are we getting a timer message that isn't ours?"); if ((int)m.WParam == _timerID) { _owner.OnTick(EventArgs.Empty); return; } } else if (m.Msg == NativeMethods.WM_CLOSE) { // this is a posted method from another thread that tells us we need // to kill the timer. The handle may already be gone, so we specify it here. // StopTimer(true, m.HWnd); return; } base.WndProc(ref m); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- XPathBinder.cs
- CompressionTransform.cs
- ParentQuery.cs
- TransformPattern.cs
- RequestTimeoutManager.cs
- OpenTypeCommon.cs
- GuidelineSet.cs
- LateBoundBitmapDecoder.cs
- MultipartContentParser.cs
- RequestQueryParser.cs
- TextRangeEditLists.cs
- ScriptingSectionGroup.cs
- HtmlElement.cs
- RectIndependentAnimationStorage.cs
- WindowsMenu.cs
- SingleConverter.cs
- EventTrigger.cs
- AbstractSvcMapFileLoader.cs
- ProtocolProfile.cs
- ButtonStandardAdapter.cs
- DiscoveryServiceExtension.cs
- Int64AnimationBase.cs
- EventLogInformation.cs
- MethodRental.cs
- NullRuntimeConfig.cs
- dbdatarecord.cs
- Socket.cs
- Canvas.cs
- DetailsViewUpdateEventArgs.cs
- TextReader.cs
- TreeNodeBinding.cs
- FileStream.cs
- DetailsViewInsertedEventArgs.cs
- HtmlTableCell.cs
- recordstatescratchpad.cs
- XmlTypeAttribute.cs
- ControlTemplate.cs
- CompensationParticipant.cs
- LambdaCompiler.Logical.cs
- EditorAttribute.cs
- Attributes.cs
- DayRenderEvent.cs
- FixedDocument.cs
- WeakHashtable.cs
- TransportContext.cs
- ResourceDisplayNameAttribute.cs
- Bidi.cs
- DataTrigger.cs
- MarkupCompilePass2.cs
- TdsParserSessionPool.cs
- RoleManagerEventArgs.cs
- InvalidCommandTreeException.cs
- TaskCanceledException.cs
- XsdDateTime.cs
- HopperCache.cs
- Operand.cs
- FocusTracker.cs
- FormatterServicesNoSerializableCheck.cs
- PageStatePersister.cs
- PropertyGeneratedEventArgs.cs
- MobileCapabilities.cs
- SystemWebCachingSectionGroup.cs
- DataGridHeaderBorder.cs
- CompressionTracing.cs
- BindingExpressionUncommonField.cs
- ToolStripGrip.cs
- ListView.cs
- SoapAttributeAttribute.cs
- DataGridViewToolTip.cs
- SamlSubject.cs
- PolicyManager.cs
- UnsafeNetInfoNativeMethods.cs
- DataGridViewControlCollection.cs
- DictionaryBase.cs
- CapabilitiesSection.cs
- RemotingServices.cs
- X509ThumbprintKeyIdentifierClause.cs
- CustomPopupPlacement.cs
- GenericsInstances.cs
- Overlapped.cs
- CalloutQueueItem.cs
- TypeValidationEventArgs.cs
- PropertyTab.cs
- PersonalizationAdministration.cs
- GeometryModel3D.cs
- TaskCanceledException.cs
- XmlHierarchicalEnumerable.cs
- StreamGeometry.cs
- Win32Exception.cs
- UnitySerializationHolder.cs
- CodeDomSerializer.cs
- MenuItemStyle.cs
- OleAutBinder.cs
- ChameleonKey.cs
- BindingMAnagerBase.cs
- CompilerResults.cs
- CodeMemberMethod.cs
- Page.cs
- Themes.cs
- TabRenderer.cs