【问题标题】:Declaration of API SetTimer?API SetTimer 的声明?
【发布时间】:2020-01-10 14:37:39
【问题描述】:

我在我的 VB 代码(在 Windows 10 64 位和 Excel 64 位下)中声明了SetTimer,如下所示:

#If Win64 Then                              ' 64-bit Windows
                                            ' ---------------
  #If VBA7 Then                             ' 64-bit Excel:
                                            ' -------------

    Public Declare PtrSafe Function SetTimer Lib "user32" (ByVal hwnd As LongPtr, _
                                                           ByVal nIDEvent As LongPtr, _
                                                           ByVal uElapse As Long, _
                                                           ByVal lpTimerFunc As LongPtr) As LongPtr
    Public settimer_result As LongPtr       ' Result value of SetTimer.
    Public Declare PtrSafe Function KillTimer Lib "user32" (ByVal hwnd As LongPtr, _
                                                            ByVal nIDEvent As LongPtr) As Long
    Public killtimer_result As Long         ' Result value of KillTimer.

...
    Public Const timer_interval As Long = 1000    
...

当我运行程序时它工作正常,但是一旦我设置一个断点进行调试,Excel 就会在以下语句处崩溃:

settimer_result = SetTimer(0&, 0&, timer_interval, AddressOf TimerProc)

我也尝试过使用LongLong 而不是LongPtr,但它仍然崩溃。

非常感谢您对此的任何帮助。

【问题讨论】:

  • Doesn't 0& 只是声明为文字 Long 但由于您的 LongPtr 声明,它会立即在 64 位 Excel 上转换为 LongLong?我会取消 & 符号,它们是为了确保将正确类型的数据(长而不是整数)传递给弱类型声明,但你的声明是强类型的,所以你不需要它们。虽然如果这是导致崩溃的原因,我会感到惊讶。
  • 嗨 Greedo,感谢您的建议。我试过了,但它仍然崩溃。还有什么建议吗?最好的问候,每安德斯

标签: vba


【解决方案1】:

您似乎误解了条件编译常量的含义。

Win64 不是“64 位 Windows”,它告诉您 Office 的位数。

VBA7 不是“64 位 Office”,它告诉您 Office 是否足够新以支持 LongPtr 类型和 PtrSafe 关键字,无论位数如何。

因此,正确的声明应该是

#If VBA7 Then

Public Declare PtrSafe Function SetTimer Lib "user32" (ByVal hwnd As LongPtr, _
                                                       ByVal nIDEvent As LongPtr, _
                                                       ByVal uElapse As Long, _
                                                       ByVal lpTimerFunc As LongPtr) As LongPtr

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

Public settimer_result As LongPtr       ' Result value of SetTimer.

#Else

Public Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, _
                                               ByVal nIDEvent As Long, _
                                               ByVal uElapse As Long, _
                                               ByVal lpTimerFunc As Long) As Long

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

Public settimer_result As Long       ' Result value of SetTimer.

#End If

Public killtimer_result As Long         ' Result value of KillTimer.

注意你do not need 使用#If Win64

如果您的TimerProc sub 具有correct argumentsLongPtrLongLongPtrLong),那么很可能IDE 是unable to keep receiving the timer callbacks,同时设置了断点,所以它崩溃了。

【讨论】:

  • 感谢您的回答 GSerg,但即使我使用您的声明,它仍然会崩溃。我从这个答案中得到了条件组合常量的组合:stackoverflow.com/questions/20269844/… 还有其他想法我能做什么吗?
  • 我认为这不是声明的问题,而是 Timer API 的敏感特性问题。例如 1. 如果 TimerProc 子有错误,Office 应用程序崩溃。 2. 如果 TimerProc 子递归调用自身,Office 应用程序崩溃。 3.如果关闭文档后已经启动的Timer没有被杀死,Office应用程序会在一段时间后崩溃。像上述情况一样,如果例程受到断点之类的干扰,我认为应用程序会在那里崩溃。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-15
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
相关资源
最近更新 更多