我正在一个仅使用 VBA 作为语言的开发工作室之上开发软件。(不是 MS 办公应用程序之一)工作室和服务应用程序只有 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 自动化:没有这样的属性或方法。
我究竟做错了什么?
编辑: 我在WWB 的文档上读到,如果子没有其他引用,它可能会被删除,从而导致 AddressOf 无效。但是,我也尝试获取我知道仍会在内存中的 sub 的地址,并且我收到相同的错误消息。
Edit2: 我创建了一个使用 PeekMessage 查找 WM_TIMER 的 while 循环。它确实被发送了。lParam 应该包含传递给 SetTimer 的函数指针。它包含一个唯一的 8 位十进制数字,多次调用时相同,但在应用程序重新启动时会发生变化。(可能是一个指针值)。但是,仍然没有调用回调(除非我手动这样做。)
我正在做的重点是避免循环等待,因为我无法访问顶级消息循环。