Code:
/ FX-1434 / FX-1434 / 1.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
- XmlDocumentFragment.cs
- HostProtectionException.cs
- PropertyState.cs
- CustomAttribute.cs
- InputLanguageProfileNotifySink.cs
- TypeUtil.cs
- RegexRunnerFactory.cs
- ThreadSafeList.cs
- BuiltInExpr.cs
- CheckBoxAutomationPeer.cs
- RichTextBoxAutomationPeer.cs
- AnnotationResource.cs
- GridPattern.cs
- PrintPageEvent.cs
- CommandDesigner.cs
- XMLSchema.cs
- RemotingException.cs
- Encoder.cs
- ImageMetadata.cs
- DefaultTraceListener.cs
- ServiceHost.cs
- Vector3DAnimation.cs
- ImmutableObjectAttribute.cs
- StandardCommandToolStripMenuItem.cs
- TimeSpanOrInfiniteValidator.cs
- CompiledRegexRunnerFactory.cs
- CompoundFileStreamReference.cs
- OptimalTextSource.cs
- GridViewColumnCollection.cs
- MachineKeySection.cs
- TextTreeNode.cs
- PrintDialogDesigner.cs
- RemoteWebConfigurationHostStream.cs
- translator.cs
- Rotation3DKeyFrameCollection.cs
- AssociationSetMetadata.cs
- RoleService.cs
- InfoCard.cs
- ObjectPersistData.cs
- BuildProvider.cs
- TextEditor.cs
- _BaseOverlappedAsyncResult.cs
- HttpStaticObjectsCollectionWrapper.cs
- SendMessageChannelCache.cs
- FileDialog.cs
- Point3DCollection.cs
- AspCompat.cs
- TransactionContext.cs
- ReturnValue.cs
- FormatConvertedBitmap.cs
- PathFigureCollectionConverter.cs
- MetaType.cs
- Matrix.cs
- ListDataBindEventArgs.cs
- ListMarkerLine.cs
- HostDesigntimeLicenseContext.cs
- __Error.cs
- DecoderExceptionFallback.cs
- ListBoxChrome.cs
- RegisteredScript.cs
- RequiredFieldValidator.cs
- ImplicitInputBrush.cs
- DateTimeFormatInfo.cs
- SerializationInfo.cs
- ButtonFieldBase.cs
- PrinterSettings.cs
- EmulateRecognizeCompletedEventArgs.cs
- securitycriticaldata.cs
- DataReceivedEventArgs.cs
- UrlPath.cs
- MemberAccessException.cs
- Array.cs
- PersistChildrenAttribute.cs
- CheckedPointers.cs
- CachingParameterInspector.cs
- WeakReference.cs
- ExpressionLexer.cs
- SelectionHighlightInfo.cs
- HTTPNotFoundHandler.cs
- GridEntry.cs
- DataGridViewRowDividerDoubleClickEventArgs.cs
- PageSetupDialog.cs
- SkipStoryboardToFill.cs
- xmlsaver.cs
- _ContextAwareResult.cs
- MenuCommandService.cs
- ThreadExceptionEvent.cs
- RegisteredDisposeScript.cs
- TryLoadRunnableWorkflowCommand.cs
- DataGridViewColumnCollection.cs
- OleDbException.cs
- SubclassTypeValidator.cs
- XmlName.cs
- Trace.cs
- MapPathBasedVirtualPathProvider.cs
- ReadWriteSpinLock.cs
- RowType.cs
- InvokePattern.cs
- VariableDesigner.xaml.cs
- FixedDocument.cs