【问题标题】:Expression cannot be converted to long error表达式无法转换为长错误
【发布时间】:2016-07-25 08:37:15
【问题描述】:

我收到以下错误,不知道如何解决: BC30581:Adressoff 表达式无法转换为 Long,因为 Long 不是委托类型。

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 TimerID As Long
Public TimerSeconds As Single


Sub StartTimer()
    TimerSeconds = 1000 ' how often to "pop" the timer.
    TimerID = SetTimer(0&, 0&, TimerSeconds * 1000&, AddressOf TimerProc)
End Sub

Sub EndTimer()
    On Error Resume Next
    KillTimer(0&, TimerID)
End Sub

Sub TimerProc(ByVal HWnd As Long, ByVal uMsg As Long,
    ByVal nIDEvent As Long, ByVal dwTimer As Long)

    MsgBox("test123")

End Sub

【问题讨论】:

  • 您在哪一行得到错误?您可以发布其余代码吗?
  • 这部分会产生错误:AddressOf TimerProc)
  • BC30581 是来自 VB.NET 编译器的错误,你确定你是用 VBA 编程吗?

标签: vb.net


【解决方案1】:

您的PInvoke signature 似乎是错误的。试试这个:

Public Delegate Sub TimerProc(ByVal hWnd As IntPtr, ByVal uMsg As UInteger, ByVal nIDEvent As IntPtr, ByVal dwTime As UInteger)

<DllImport("user32.dll", SetLastError:=True)> _
Public Shared Function SetTimer(ByVal hWnd As IntPtr, ByVal nIDEvent As IntPtr, ByVal uElapse As UInteger, ByVal lpTimerFunc As TimerProc) As IntPtr
End Function

您还需要更改 KillTimer 的 pinvoke 签名。有关详细信息,请参阅 pinvoke.net。

【讨论】:

    【解决方案2】:

    我得到了它的工作:

    Imports System.Runtime.InteropServices
    
    Public Class TimerMethods
    
        <DllImport("user32.dll", SetLastError:=True)>
        Public Shared Function SetTimer(ByVal hWnd As IntPtr, ByVal nIDEvent As IntPtr, ByVal uElapse As UInteger, ByVal lpTimerFunc As TimerProc) As IntPtr
        End Function
    
        <DllImport("user32.dll", SetLastError:=True)>
        Public Shared Function KillTimer(ByVal hWnd As IntPtr, ByVal nIDEvent As IntPtr) As Boolean
        End Function
    
        Public Delegate Sub TimerProc(ByVal hWnd As IntPtr, ByVal uMsg As UInteger, ByVal nIDEvent As IntPtr, ByVal dwTime As UInteger)
    
        Public timerID As IntPtr
    
        Sub StartTimer(windowHandle As IntPtr)
            Dim timerSeconds = 3 ' how often to "pop" the timer.
            timerID = SetTimer(windowHandle, IntPtr.Zero, CUInt(timerSeconds * 1000), AddressOf TimerMethods.TimerCallback)
    
            If timerID = IntPtr.Zero Then
                Debug.WriteLine("Timer start error.")
            Else
                Debug.WriteLine("Timer started.")
            End If
    
        End Sub
    
        Sub EndTimer()
            KillTimer(IntPtr.Zero, timerID)
    
        End Sub
    
        Public Shared Sub TimerCallback(ByVal hWnd As IntPtr, ByVal uMsg As UInteger, ByVal nIDEvent As IntPtr, ByVal dwTime As UInteger)
            MsgBox(uMsg)
    
        End Sub
    
    End Class
    

    还有一个简单的表格,上面只有一个按钮来启动计时器:

    Public Class Form1
    
        Dim t As TimerMethods
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            t = New TimerMethods
            t.StartTimer(Me.Handle)
    
        End Sub
    
        Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
            If t IsNot Nothing Then
                t.EndTimer()
            End If
    
        End Sub
    
    End Class
    

    您不必使用windowHandle 将计时器绑定到表单:您可以改用IntPtr.Zero

    每当您看到像hWnd 这样的变量名时,它都需要一个句柄,即VB.NET 中的IntPtr

    参考:pinvoke.net/default.aspx/user32.SetTimer

    【讨论】:

      【解决方案3】:

      使用 PInvoke 执行此操作似乎没什么意义。有一个您可以轻松使用的 Windows 窗体计时器:

      Public Class Form3
      
          Private _timer As Timer
      
          Public Sub StartTimer()
              _timer = New Timer()
              _timer.Interval = 1000 ' timer interval in ms
              AddHandler _timer.Tick, AddressOf TimerProc
              _timer.Enabled = True
          End Sub
      
          Public Sub EndTimer()
              _timer.Enabled = False
              RemoveHandler _timer.Tick, AddressOf TimerProc
          End Sub
      
          Sub TimerProc(sender As Object, e As EventArgs)
              MsgBox("test123")
          End Sub
      End Class
      

      【讨论】:

        【解决方案4】:

        我已经在 Excel 2013 中测试了 VBE 中的代码并成功运行。

        【讨论】:

        • 对不起标题不正确,我在VB.NET中编程
        【解决方案5】:

        我事先声明此解决方案适用于VBA 环境

        因为在我写它的阶段这是可能的

        我做了一些修改让它运行:

        • SetTimer()KillTimer () 函数声明的最后一行的末尾添加了继续转义序列“_

        • EndTimer() 中将KillTimer 分配给Long 变量,我也声明了该变量

        • TimerProc() 中添加了对 EndTimer() 的调用以停止它!!!

        下面是我的工作代码:

        Option Explicit
        
        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 TimerID As Long
        Public TimerSeconds As Single
        
        
        Sub StartTimer()
            TimerSeconds = 1000 ' how often to "pop" the timer.
            TimerID = SetTimer(0&, 0&, TimerSeconds * 1000&, AddressOf TimerProc)
        End Sub
        
        Sub EndTimer()
            Dim i As Long '<--| added
            On Error Resume Next
            i = KillTimer(0&, TimerID) '<--| added
        End Sub
        
        
        Sub TimerProc(ByVal HWnd As Long, ByVal uMsg As Long, _
            ByVal nIDEvent As Long, ByVal dwTimer As Long)
        
            MsgBox ("test123")
        
            EndTimer '<--| added !!!
        End Sub
        

        【讨论】:

        • @ChrisDunaway:我正在写上面的内容,当时有人澄清这不是 VBA 环境。请删除反对票。谢谢
        • 了解,但对于this 问题的答案仍然不正确。另一个 VB.Net 用户可能会遇到这个答案,但对他们不起作用。
        • 您好,感谢您的帮助。但是我仍然收到代码最后一部分的错误: TimerID = SetTimer(0&, 0&, TimerSeconds * 1000&, AddressOf TimerProc)
        • 对不起,我帮不了你。不要招致进一步的@ChrisDunaway 最精确的反对票......
        • @ChrisDunaway,我的答案是:“在 VBA 中,我通过一些编辑使它运行:”。对于任何可能遇到它的 VB.Net 用户来说,这还不够清楚吗?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多