Я занимаюсь разработкой программного обеспечения поверх студии разработки, которая использует только VBA в качестве языка. (Не одно из приложений MS Office) Студийные и сервисные приложения являются только 32-битными, даже если они выполняются на 64-битной машине. В этой среде для взаимодействия используется WinWrap Basic 9.1.
Я пытаюсь внедрить систему таймера и поэтому обратился к коду взаимодействия, чтобы это произошло. Это код, который я поместил в модуль кода (.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
Кажется, он работает нормально, возвращая уникальный timerID
каждый раз, когда я вызываю pSetTimer. Однако timerCallback
никогда не вызывается.
В других руководствах по импорту SetTimer
используется тип Long
вместо делегата. Но если я попытаюсь это сделать (или если я попытаюсь преобразовать вывод AddressOf timerCallback
в Long или String с целью ведения журнала), он выдаст следующую ошибку:
[10091] ActiveX Automation: нет такого свойства или метода.
Что я делаю не так?
Редактировать: Я читаю Документ WWB что если подпрограмма не имеет других ссылок, она может быть удалена, что делает AddressOf недействительным. Тем не менее, я также попытался взять адрес сабвуфера, который, как я знаю, все еще будет в памяти, и я получил тот же результат.
Edit2: Я создал цикл while, который используетPeekMessage, чтобы найти WM_TIMER. И это отправили. Предполагается, что lParam содержит указатель на функцию, переданный в SetTimer. И он содержит уникальный 8-значный десятичный номер, который совпадает с несколькими вызовами, но изменяется при каждом перезапуске приложения. (вероятно, чтобы быть значением указателя). Однако обратный вызов все еще не вызывается (если я не делаю это вручную.)
Смысл того, что я делаю, состоит в том, чтобы избежать ожидания цикла, поскольку у меня нет доступа к циклу сообщений верхнего уровня.