I am developing software on top of a development studio that only uses VBA as a language. (Not one of MS office applications) The studio and service applications are 32bit only, even though they are being executed on a 64bit machine. This environment uses WinWrap Basic 9.1.
I am trying to implement a timer system and so I've turned to Interop code to make it happen. This is the code I've placed in a code module (.bas):
Private Sub timerCallback(ByVal hWnd As Long, ByVal msg As Long, ByVal tmrID As Long, ByVal msDelta As Long)
'...
End Sub
Private timerID As Long
Private Sub pSetTimer()
'// set timer to 50ms
timerID = SetTimer(0, timerID, 50, AddressOf timerCallback)
End Sub
Private Sub pResetTimer()
If KillTimer(0, timerID) Then timerID = 0
End Sub
Private Delegate Sub TIMERPROC(ByVal hWnd As Long, ByVal msg As Long, ByVal tmrID As Long, ByVal msDelta As Long)
Private Declare Function SetTimer Lib "User32.dll" (ByVal hWnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As TIMERPROC) As Long
Private Declare Function KillTimer Lib "User32.dll" (ByVal hWnd As Long, ByVal nIDEvent As Long) As Boolean
It seems to work just fine, returning a unique timerID
each time I call pSetTimer. However, the timerCallback
never gets called.
Other guides out there that import SetTimer
use Long
type instead of a delegate. But if I try to do so (or if I try to convert the output of AddressOf timerCallback
to a Long or String for the purpose of logging), then it throws the following error:
[10091] ActiveX Automation: no such property or method.
What am I doing wrong?
Edit: I read on WWB's doc that if the sub has no other references it may be deleted rendering the AddressOf invalid. However, I have also tried taking the address of a sub that I know will still be in memory and I get the same error message.
Edit2: I've created a while loop that uses PeekMessage to find the WM_TIMER. And it does get sent. The lParam is supposed to contain the function pointer passed to SetTimer. And it contains a unique 8 digit decimal number, which is the same with multiple calls, but changes whenever the app is restarted. (probable to be a pointer value). However, the callback is still not being called (unless I do so manually.)
The point of what I'm doing is to avoid loop waiting as I don't have access to the top level message loop.