home *** CD-ROM | disk | FTP | other *** search
Visual Basic class definition | 1997-01-08 | 6.5 KB | 186 lines |
- VERSION 1.0 CLASS
- BEGIN
- MultiUse = -1 'True
- END
- Attribute VB_Name = "XTimer"
- Attribute VB_GlobalNameSpace = False
- Attribute VB_Creatable = True
- Attribute VB_PredeclaredId = False
- Attribute VB_Exposed = True
- Option Explicit
- '===============================================
- ' WARNING! DO NOT press the End button while
- ' debugging this project! See explanation
- ' at the top of the XTimerSupport module
- ' (XTimerS.bas).
- '===============================================
-
- ' Private storage for XTimer properties:
- Private mlngTimerID As Long
- Private mlngInterval As Long
- Private mblnEnabled As Boolean
-
- ' The XTimer's only event is Tick. XTimer's Tick event
- ' doesn't have any arguments (eliminating arguments speeds
- ' up the event slightly), but there's no reason why you
- ' couldn't supply arguments if you wanted to.
- Event Tick()
-
- ' TimerID property is required by the EndTimer procedure,
- ' ---------------- in order to quickly locate the timer
- ' in the support module's array of active timers.
- '
- ' There's no reason for the client to use this property,
- ' so it's declared Friend instead of Public.
- '
- Friend Property Get TimerID() As Long
- TimerID = mlngTimerID
- End Property
-
- ' Enabled property turns the timer on and off. This is
- ' ---------------- done by killing the system timer,
- ' because there's no way to suspend a system timer.
- ' If they exist, they're running.
- '
- Public Property Get Enabled() As Boolean
- Enabled = mblnEnabled
- End Property
- '
- Public Property Let Enabled(ByVal NewValue As Boolean)
- ' If there's no change to the state of
- ' the property, then exit. This
- ' prevents starting a second system
- ' timer when one is already running,
- ' etcetera.
- If NewValue = mblnEnabled Then Exit Property
- '
- ' Save the new property setting.
- mblnEnabled = NewValue
- '
- ' If the Interval is zero, the timer
- ' is already stopped. Don't start it.
- If mlngInterval = 0 Then Exit Property
- '
- ' Turn timer on or off.
- If mblnEnabled Then
- Debug.Assert mlngTimerID = 0
- mlngTimerID = BeginTimer(Me, mlngInterval)
- Else
- ' The following is necessary, because
- ' an XTimer can shut off its system
- ' timer two ways: Enabled = False,
- ' or Interval = 0.
- If mlngTimerID <> 0 Then
- Call EndTimer(Me)
- mlngTimerID = 0
- End If
- End If
- End Property
-
- ' Interval property must do more than just set the
- ' ----------------- timer interval. If the XTimer
- ' is enabled, and the Interval is changed from zero
- ' to a non-zero value, then a system timer must be
- ' started. Likewise, if the Interval is changed
- ' to zero, the system timer must be stopped.
- '
- ' The Property Let procedure also ends one system timer
- ' and starts another whenever the interval changes.
- ' This is because there's no way to change the
- ' interval of a system timer.
- '
- Public Property Get Interval() As Long
- Interval = mlngInterval
- End Property
- '
- Public Property Let Interval(ByVal NewInterval As Long)
- ' If the new value for Interval is the same as the old,
- ' there's no reason to do anything.
- If NewInterval = mlngInterval Then Exit Property
- '
- ' Save the new value.
- mlngInterval = NewInterval
- '
- ' If the XTimer is active, mlngTimerID is non-zero.
- ' in this case, the old system timer must be
- ' ended before a new one is started.
- If mlngTimerID <> 0 Then
- Call EndTimer(Me)
- mlngTimerID = 0
- End If
- '
- ' If the new interval is zero, then the XTimer
- ' becomes inactive, regardless of the current
- ' value of Enabled. If the new interval is
- ' not zero, AND the Enabled property is True,
- ' then a new system timer is started, and its
- ' ID is stored in mlngTimerID.
- If (NewInterval <> 0) And mblnEnabled Then
- mlngTimerID = BeginTimer(Me, NewInterval)
- End If
- End Property
-
- ' RaiseTick method is called by the support module when
- ' ---------------- the system timer event occurs for
- ' this XTimer object's system timer.
- '
- ' Implementation detail: You might expect to declare
- ' this method Friend instead of Public, as there's
- ' no need for the client to call RaiseTick. However,
- ' it's critical that RaiseTick be declared Public,
- ' because the XTimer might be released while the
- ' Tick event is still being handled. An object will
- ' not terminate while one of its Public methods is
- ' on the stack, but it CAN terminate while one of its
- ' Friend methods is on the stack. If the object
- ' terminates before the Friend method returns (which
- ' could happen if the client executes a lot of code
- ' in the XTimer's Tick event), a GPF will result.
- ' (Note that this is a highly unusual scenario that
- ' depends on an external event; it does not occur in
- ' ordinary use of Friend functions.)
- '
- Public Sub RaiseTick()
- RaiseEvent Tick
- End Sub
-
- Private Sub Class_Terminate()
- ' When the client releases its last reference to
- ' an XTimer object, it goes away -- but only
- ' if the XTimer's Enabled property is False,
- ' or its Interval property is True!
- '
- ' This is because while the XTimer's system
- ' timer is running, the XTimerSupport module
- ' has to have a reference to the XTimer in
- ' order to raise its Tick event. Thus,
- ' failure of the client to disable XTimer
- ' objects before releasing them will LEAK
- ' system timers!
- '
- ' These leaked system timers will not be
- ' recovered until the XTimers component shuts
- ' down -- that is, when the client using
- ' the DLL shuts down. The DLL will NOT
- ' unload when all XTimer objects are released,
- ' because references to public objects (in
- ' this case, those held by XTimerSupport)
- ' will prevent a DLL from unloading.
- '
- ' So why bother to clean up the system timer
- ' in the Terminate event? Because when the
- ' DLL is getting shut down, all references
- ' to the XTimer object will be cleaned up
- ' -- and the XTimer will get its Terminate
- ' event. The system timer should be
- ' destroyed at this point.
- On Error Resume Next
- If mlngTimerID <> 0 Then KillTimer 0, mlngTimerID
- '
- ' The following is what XTimer should do if
- ' it could somehow be released prior to
- ' DLL shutdown.
- 'If mlngTimerID <> 0 Then Call EndTimer(Me)
- End Sub
-
-