- •Лекция 13
- •XTimers.Vbp 5
- •Обзор задачи Coffee Sample Application
- •XTimers.Vbp
- •XTimerSupport.Bas
- •Private Type xtimerinfo ' Hungarian xti
- •Public Sub TimerProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal idEvent As Long, ByVal lngSysTime As Long)
- •If maxti(intCt).BlnReentered Then Exit Sub
- •Public Sub EndTimer(ByVal xt As xTimer)
- •Public Sub Scrub()
- •Public Property Get Interval() As Long
- •Public Property Let Interval(ByVal NewInterval As Long)
- •Public Sub RaiseTick()
- •Private Sub Class_Terminate()
- •MtCoffee.Vbp modMt.Bas Option Explicit
- •Public glngGlobalData As Long
- •Coffee.Bas
- •Option Explicit
- •Private Declare Function timeGetTime Lib "winmm.Dll" () As Long
- •Private mlngIterations As Long
- •Public Property Get NumberOnThread() As Long
- •Public Sub StartLongTask(ByVal Iterations As Long)
- •Public Function GetCoffeeOnSameThread() As Coffee
- •Public Function GetCoffeeOnNewThread() As Coffee
- •If blnCancel Then
- •Coffee.Cls Option Explicit Private Declare Function timeGetTime Lib "winmm.Dll" () As Long
- •Private mlngIterations As Long
- •Public Property Get NumberOnThread() As Long
- •Public Sub StartLongTask(ByVal Iterations As Long)
- •Public Function GetCoffeeOnSameThread() As Coffee
- •Public Function GetCoffeeOnNewThread() As Coffee
- •If blnCancel Then
- •Public Property Get CoffeeMonitor() As CoffeeMonitor
- •If gCoffeeMonitor Is Nothing Then
- •CoffeeMonitor.Cls Option Explicit
- •Private WithEvents mwXTimer As xTimer
- •Event CoffeeReady() Private Sub Class_Initialize()
- •Private Sub Class_Terminate()
- •Private Sub mwXTimer_Tick()
- •Connector2.Cls Option Explicit
- •Public Property Get CoffeeMonitor2() As CoffeeMonitor2
- •CoffeeMonitor2 Option Explicit
- •Private maicnClients() As iCoffeeNotify
- •Public Sub TellMeReady(ByVal icn As iCoffeeNotify)
- •Public Sub CeaseCallBacks(ByVal icn As iCoffeeNotify)
- •Private Sub mwXTimer_Tick()
- •ICoffeeNotify.Cls
- •Public ThreadId As Long
- •Private Sub mwCoffee_Progress(ByVal PercentDone As Single, Cancel As Boolean)
- •Private Sub cmdCallBacks_Click()
- •Private Sub cmdMt_Click()
- •Private Sub Form_Unload(Cancel As Integer)
- •Private Sub mwcmnEvents_CoffeeReady()
- •FrmThread.Frm
- •Private Sub cmdCancel_Click()
- •Private Sub cmdShortOnly_Click()
- •Private Sub cmdShortLong_Click()
- •Private Sub cmdNLong_Click()
- •Private Sub cmdXThread_Click()
- •Private Sub cmdIDs_Click()
- •Private Sub tmrShort_Timer()
XTimers.Vbp
XTimerSupport.Bas
Option Explicit
'================================================
' WARNING! DO NOT press the End button while debugging this project! While in Break mode, do NOT make edits that reset the project!
'' This module is dangerous because it uses the SetTimer API and the AddressOf operator to set up a code-only timer. Once such a timer is set up, the system will continue to call the TimerProc function EVEN AFTER YOU RETURN TO DESIGN TIME. Since TimerProc isn't available at design time, the system will cause a PROGRAM FAULT in Visual Basic.
' When debugging this module, you need to make sure that all system timers have been stopped (using KillTimer) before returning to design time. You can do this by calling SCRUB from the Immediate window.
'Call-back timers are inherently dangerous. It's much safer to use Timer controls for most of your development process, and only switch to call-back timers at the very end.
'==================================================
' Amount to increase size of the array maxti when more active timers are needed. (See 'MoreRoom:' below.)
Const MAXTIMERINCREMEMT = 5
Private Type xtimerinfo ' Hungarian xti
xt As XTimer
id As Long
blnReentered As Boolean
End Type
Declare Function SetTimer Lib "user32" (ByVal hWnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerProc As Long) As Long
Declare Function KillTimer Lib "user32" (ByVal hWnd As Long, ByVal nIDEvent As Long) As Long
' maxti is an array of active XTimer objects. The reason for using an array of user-defined types instead of a Collection object is to get early binding when we raise the XTimer object's Tick event.
Private maxti() As XTIMERINFO
'' mintMaxTimers tells us how large the array maxti is at any given time.
Private mintMaxTimers As Integer
' BeginTimer function is called by an XTimer object when the XTimer's Interval property is set to a new non-zero value. The function makes the API calls required to set up a timer. If a timer is successfully created, the function puts a reference to the XTimer object into the array maxti. This reference will be used to call the method that raises the XTimer's Tick event.
Public Function BeginTimer(ByVal xt As XTimer, ByVal Interval As Long)
Dim lngTimerID As Long
Dim intTimerNumber As Integer
lngTimerID = SetTimer(0, 0, Interval, AddressOf TimerProc)
' Success is a non-zero return from SetTimer. If we can't get a timer, raise an error.
If lngTimerID = 0 Then Err.Raise vbObjectError + 31013, , "No timers available"
' The following loop locates the first available slot in the array maxti. If the upper bound is exceeded, an error occurs and the array is made larger. (If you compile this DLL to Native Code, DO NOT turn off Bounds Checking!)
For intTimerNumber = 1 To mintMaxTimers
If maxti(intTimerNumber).id = 0 Then Exit For
Next
'
' If no empty space was found, increase the size of the array.
If intTimerNumber > mintMaxTimers Then
mintMaxTimers = mintMaxTimers + MAXTIMERINCREMEMT
ReDim Preserve maxti(1 To mintMaxTimers)
End If
' Save a reference to use when raising the XTimer object's Tick event.
Set maxti(intTimerNumber).xt = xt
'
' Save the timer id returned by the SetTimer API, and return the value to the XTimer object.
maxti(intTimerNumber).id = lngTimerID
maxti(intTimerNumber).blnReentered = False
BeginTimer = lngTimerID
End Function
' TimerProc is the timer procedure which the system will call whenever one of your timers goes off.
'' IMPORTANT -- Because this procedure must be in a standard module, all of your timer objects must share it. This means the procedure must identify which timer has gone off. This is done by searching the array maxti for the ID of the timer (idEvent).
' If this Sub declaration is wrong, PROGRAM FAULTS will occur! This is one of the dangers of using APIs that require call-back functions.