调用Delegate Lib API时出现错误,检测到InValidFunctionPointerInDelegate

时间:2017-06-07 13:30:17

标签: .net vb.net delegates

Dim fl_prevproc As SubClassProcDelegate

我创建了如下功能:

Public Function SetupClassNotification() As Boolean
   Dim subclassform As System.Windows.Forms.Form
   Dim i As Integer
      For i = 0 To FORMLIST_END 
        If Formlist(i).fl_threadid = 0 Then 
        subclassform = New frmSubclassingForm 
        subclassform.Hide() 
        Formlist(i).fl_prevproc = SetWindowLong(subclassform.Handle.ToInt32, GWL_WNDPROC, AddressOf WindowProc)
        Exit Function
        End If
      Next i
End Function

实现具有与委托函数完全相同的WindowProc函数

Private Function WindowProc(ByVal hw As Integer, ByVal uMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

    Dim i As Integer

    If uMsg = VB_WM_USER_PLUS_1 Then 

        CheckForResponses() 
    Else 
        For i = 0 To FORMLIST_END 
            If hw = Formlist(i).fl_gHW Then 
                WindowProc = CallWindowProc(Formlist(i).fl_prevproc, hw, uMsg, wParam, lParam) 
            End If
        Next i
    End If
End Function

Lib API声明如下:

Delegate Function SubClassProcDelegate(ByVal hw As Integer, ByVal uMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

Declare Function CallWindowProc Lib "user32.dll" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As SubClassProcDelegate, ByVal hwnd As Integer, ByVal msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" (ByVal hwnd As Integer, ByVal attr As Integer, ByVal lVal As SubClassProcDelegate) As SubClassProcDelegate

执行停在一行:

Formlist(i).fl_prevproc = SetWindowLong(subclassform.Handle.ToInt32, GWL_WNDPROC, AddressOf WindowProc)

我收到的错误消息是

  

无效的函数指针0xffff0a95被传递到运行时   转换为代表。传入无效的函数指针   转换为代理可能会导致崩溃,损坏或数据丢失。

任何帮助将不胜感激。谢谢。

1 个答案:

答案 0 :(得分:1)

将窗口句柄声明为Integer会引发问题,尤其是在使用64位操作系统时;使用IntPtrSafeHandlewParamlParam也应该是IntPtr。

那说,为什么不使用.Net NativeWindow Class挂钩窗口程序?

编辑:

以下是使用Win32 API的工作示例。我仍然建议你实现一个基于NativeWindow类的解决方案。

Imports System.Runtime.InteropServices

Public Class Form1
    Private prevWndProc As IntPtr
    Public Delegate Function WndProcDelegate(ByVal hWnd As IntPtr, ByVal msg As UInt32, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr

    <System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint:="SetWindowLong")> _
    Private Shared Function SetWindowLong32(ByVal hWnd As IntPtr, nIndex As Int32, ByVal dwNewLong As IntPtr) As IntPtr
    End Function

    <System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint:="SetWindowLongPtr")> _
    Private Shared Function SetWindowLongPtr64(ByVal hWnd As IntPtr, nIndex As Int32, ByVal dwNewLong As IntPtr) As IntPtr
    End Function

    Private Shared Function SetWindowProc(hwnd As IntPtr, wndProcDelegate As WndProcDelegate) As IntPtr
        Const GWL_WNDPROC As Int32 = -4

        Dim ptr As IntPtr = Marshal.GetFunctionPointerForDelegate(wndProcDelegate)
        If IntPtr.Size = 8 Then
            Return SetWindowLongPtr64(hwnd, GWL_WNDPROC, ptr)
        Else
            Return SetWindowLong32(hwnd, GWL_WNDPROC, ptr)
        End If
    End Function

    <DllImport("user32.dll")> _
    Private Shared Function CallWindowProc(lpPrevWndFunc As IntPtr, hWnd As IntPtr, Msg As UInt32, wParam As IntPtr, lParam As IntPtr) As IntPtr
    End Function

    Protected Overrides Sub OnLoad(e As EventArgs)
        MyBase.OnLoad(e)
        prevWndProc = SetWindowProc(Me.Handle, AddressOf MyWindowProcedure)
    End Sub

    Private Function MyWindowProcedure(ByVal hWnd As IntPtr, ByVal msg As UInt32, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
        Debug.Print(msg.ToString)
        Return CallWindowProc(prevWndProc, hWnd, msg, wParam, lParam)
    End Function
End Class