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被传递到运行时 转换为代表。传入无效的函数指针 转换为代理可能会导致崩溃,损坏或数据丢失。
任何帮助将不胜感激。谢谢。
答案 0 :(得分:1)
将窗口句柄声明为Integer
会引发问题,尤其是在使用64位操作系统时;使用IntPtr
或SafeHandle。 wParam
和lParam
也应该是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