jwcolby
jwcolby at colbyconsulting.com
Tue Feb 10 11:08:08 CST 2009
To this point the classes we have looked at were specifically designed to allow you to “wrap” an
object that generates events and add code and variables to process those events. This lecture will
demonstrate that classes have other uses and do not have to wrap other objects.
The class introduced today will be clsTimer, a means of timing events (things happening) in your
code. The class is perhaps the simplest class I have ever written, and perhaps the simplest class
you will ever see.
• Click Insert / Class
• Save immediately as clsTimer
• Insert the following code into the class:
Private Declare Function apiGetTime Lib "winmm.dll" _
Alias "timeGetTime" () As Long
Private lngStartTime As Long
Private Sub Class_Initialize()
StartTimer
End Sub
Function EndTimer()
EndTimer = apiGetTime() - lngStartTime
End Function
Sub StartTimer()
lngStartTime = apiGetTime()
End Sub
• Compile and save the class.
Notice that in the header of the class we have a function definition apiGetTime that calls out to
Windows. This function gets the windows tick timer and has a resolution of 1 millisecond, or one
thousandth of a second. This simply means that we can’t time anything that takes less than one
thousandth of a second without resorting to timing it several times. It returns a long integer that
is simply an absolute number of “ticks”. Since when? It doesn’t matter, it is just “this is the
tick count RIGHT NOW”.
To compute a “time” (and we aren’t really doing that, we are calculating a time since the first
time), you get the tick count and store it, then later you get another tick and compare it to the
first tick. The difference is the number of 1000ths of a second since the first tick count.
Notice that we have no mInit() method in this class. Notice also that the Class_Initialize calls
the StartTimer() function. As you know now, the Class_Initialize is a class event that fires as the
class loads, so this tells the class to load the first tick time as soon as the class instance loads.
In the header of the class we dimensioned a long variable lngStartTime. This will be used to store
the starting tick count. StartTimer() simply calls out to Windows, gets the current tick count from
Windows, and stores that count to lngStartTime.
EndTimer() simply calls out to Windows again to get the current tick count, subtracts the current
count to the previous count stored in lngStartTime and returns that count to you the programmer.
That’s it folks! This class has in the header a function definition to call Windows and a place to
store the count. In the body of the class it then has two methods to start the “timer” and to
return the ticks since the timer started. You are not going to see many classes simpler than that.
So let’s discuss why we need to encapsulate this in a class. You might be saying that you can do
the same thing without the class but a class allows you to create as many of these timers as you
want. Let’s build some test code to see how this thing works and why we might need several.
• In the tools menu click Insert / MODULE. We are building a normal module this time, NOT a class
module.
• Immediately save the module as basTimerTest
• Into this new module insert the following code:
Function TmrTest()
Dim lngCtr1 As Long
Dim lngCtr2 As Long
Dim clsTmr1 As clsTimer
Dim clsTmr2 As clsTimer
Set clsTmr1 = New clsTimer
For lngCtr1 = 1 To 5
Set clsTmr2 = New clsTimer
For lngCtr2 = 1 To 100000
Pi
Next lngCtr2
Debug.Print clsTmr2.EndTimer
Next lngCtr1
Debug.Print clsTmr1.EndTimer
End Function
Function Pi() As Double
Dim dblPi As Double
dblPi = 4 * Atn(1)
Pi = dblPi
End Function
Notice that we dim two timers, then we SET the timers on the outside of their respective loops. As
you know, the SET statement loads the class, at which point the Class_Initialize fires which grabs
the first timer tick from windows.
The Debug.Print statement simply calls the .EndTimer method of the class and prints it to the debug
window.
Voila, a timer, with a resolution of one thousandth of a second.
TmrTest simulates a real world code where you have two loops, and inner loop and an outer loop.
The inner loop times how long it takes to calculate Pi. Notice that modern computers are so fast
that I have to do it a hundred thousand times in order to get enough “tick counts” (thousandths of a
second) to even get a number to use. The outer loop simply times how long it takes to run the inner
loop 5 times.
I have intentionally kept this thing simple, but your outer loop might time how long it takes to
read a thousand records and the inner loop might be replaced with timing how long it takes to …
transform a string from comma delimited to pipe delimited or something like that.
In this lecture we have demonstrated that a class encapsulates all of the code required to perform
its function, plus the variables required to store its data. It also demonstrates that you can use
as many instances of the class as you need. If you need one or a hundred timers, you just dim and
SET the variables and you are off to the races so to speak.
Classes are used to encapsulate code and data required to implement a system. You’re your
imagination is the only limit to what that system can be.
--
John W. Colby
www.ColbyConsulting.com