Wednesday, August 20, 2008

Visual Basic 6: How to run an event at a given time (Without using the Timer Control)

Without a doubt one of the best tools that Visual Basic 6 brings to the table is the Timer Control, in my opinion. This gives you the ability to make your application perform events at given intervals without using looping delays and burning up resources, and under most circumstances it works wonders. There are some obvious limitations however, such as the Timer Interval maxing out around 64 seconds, so if you want to trigger an event at intervals of say an hour apart, you're left with a challenge.

There are a couple of ways that you can get around this limitation but I've found the following to be the "best" for the most number of situations and circumstances that I commonly encounter. It's relatively straight forward (at least for VB) but explanations are seldom as effective as a simple demonstration so, here you go.

As an example you can create a new .exe project with two buttons, one text box and a standard module. Enter the code below and then compile the project as a standard .exe.

Put the following code in the standard module:

'Start Module Code
Declare Function SetTimer Lib "user32" _
(ByVal hwnd As Long, _
ByVal nIDEvent As Long, _
ByVal uElapse As Long, _
ByVal lpTimerFunc As Long) As Long

Declare Function KillTimer Lib "user32" _
(ByVal hwnd As Long, _
ByVal nIDEvent As Long) As Long


‘This is the code that you want the timer to execute at each interval

Public Sub VB_Action(ByVal hwnd As Long, _
ByVal uMsg As Long, _
ByVal idEvent As Long, _
ByVal dwTime As Long)

Form1.Text1.Text = Now

End Sub


Place the following code within Form1.

Dim Timer_ID As Long

Private Sub Command1_Click()
'Starts the timer.
Timer_ID = SetTimer(0, 0, 1000, AddressOf VB_Action)
End Sub

Private Sub Command2_Click()
'stops the timer.
Timer_ID = KillTimer(0, Timer_ID)
End Sub

Now compile the project as a .exe.

NOTE: This example WILL NOT work correctly if you try to run it from within VB6 as an uncompiled program. The Timer will start but the KillTimer function will not stop it correctly and when you try to end the run it's likely that VB6 will crash with an error. If you compile the code to a .exe and run it, it works fine.

This simple example will basically make a VB Clock. When you click Command Button 1 the program will start updating text1 with the date / time at 1 second intervals until you either click command button 2 to stop it, or exit the program.

To use this procedure in a more practical manner you would replace VB_Action with the sub of your choice and would set the interval to whatever time frame you needed. When setting the interval you'll need to convert the interval to milliseconds - I know, it's painful - and you have a maximum interval of 2,147,483,647 milliseconds or approximately 24.8 days.

Another limitation with this method is that for the event to occur the application must remain open and running between intervals. If the application is closed or stops responding at any point then no further action will occur from that point on. I'm sure there's probably a way to cause the application to launch itself with a callback but it's not something I've needed to know how to do at this point so I can't offer any advice on that one.

I don't see any reason why this method wouldn't work for VBA as well, however it's typically easier to the use the Application.OnTime method when you're dealing with VBA. As a bonus, when using the Application.OnTime method, you can close the file between intervals and the system will automatically launch the file at the next interval.

No comments: