- 跳过对过滤器函数的调用
CallNextHookEx
通常GetMsgProc
是一个坏主意。如果您这样做,则不会调用链中的其他过滤器函数。也许,在开发机器上没有,但是“在野外”会有其他安装了钩子的应用程序。如果您阻止调用它们的过滤器函数,这些应用程序将出现异常行为。
- 您可能不想分析只是从队列中偷看但没有从队列中删除的消息。为已从队列中删除的消息
GetMsgProc
调用。wParam = PM_REMOVE
VB6 或 C++ 或其他任何东西,忽略 API 的 MSDN 规范是一种致命的做法。这就是GetMsgProc
过滤器函数应该如何根据其第一个参数的值做出决定:
代码[输入]
指定挂钩过程是否必须处理消息。如果代码是 HC_ACTION,则挂钩过程必须处理该消息。如果代码小于零,则挂钩过程必须将消息传递给 CallNextHookEx 函数而不进行进一步处理,并且应该返回 CallNextHookEx 返回的值。
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644981%28v=vs.85%29.aspx
虽然CopyMemory
应该可以工作(假设您正确声明它),但我不会在这里打扰它。将 filter 函数的第三个参数声明为ByRef lParam As MSG
.
这是应该放在标准模块中的代码(与安装挂钩的任何其他代码一样)。如果我用它来嗅探WM_RBUTTONDOWN
消息,例如TextBox
放置在主窗体上的控件,它对我有用。
Option Explicit
'http://msdn.microsoft.com/en-us/library/windows/desktop/dd162805%28v=vs.85%29.aspx
Private Type tagPOINT
x As Long
y As Long
End Type
'http://msdn.microsoft.com/en-us/library/windows/desktop/ms644958%28v=vs.85%29.aspx
Private Type MSG
hWnd As Long
message As Long
wParam As Long
lParam As Long
time As Long
pt As tagPOINT
End Type
Private bHooked As Boolean
Private hHook As Long
Private hHwndToSniff As Long
Private Const HC_Action As Long = &H0
Private Const PM_NOREMOVE As Long = &H0
Private Const PM_REMOVE As Long = &H1
Private Const WH_GETMESSAGE As Long = &H3
Private Const WM_RBUTTONDOWN As Long = &H204
'http://msdn.microsoft.com/en-us/library/windows/desktop/ms644974%28v=vs.85%29.aspx
Private Declare Function CallNextHookEx Lib "user32" _
(ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long
'http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990%28v=vs.85%29.aspx
Private Declare Function SetWindowsHookEx Lib "user32" _
Alias "SetWindowsHookExA" _
(ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
'http://msdn.microsoft.com/en-us/library/windows/desktop/ms644993%28v=vs.85%29.aspx
Private Declare Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Long) As Long
Public Sub RemoveHook()
If bHooked Then
UnhookWindowsHookEx hHook
bHooked = False
End If
End Sub
Public Sub SetHook(ByVal hThreadToHook As Long, hHwndFilter As Long)
If Not bHooked Then
hHook = SetWindowsHookEx(WH_GETMESSAGE, AddressOf GetMsgProc, 0, hThreadToHook)
If hHook > 0 Then
bHooked = True
hHwndToSniff = hHwndFilter
Else
Debug.Assert False
End If
End If
End Sub
'http://msdn.microsoft.com/en-us/library/windows/desktop/ms644981%28v=vs.85%29.aspx
Private Function GetMsgProc(ByVal uCode As Long _
, ByVal wParam As Long _
, ByRef lParam As MSG) As Long
If uCode = 0 Then
If wParam = PM_REMOVE Then
If lParam.message = WM_RBUTTONDOWN Then
If lParam.hWnd = hHwndToSniff Then
MsgBox "You right-clicked a text box!"
End If
End If
End If
End If
GetMsgProc = CallNextHookEx(hHook, uCode, wParam, lParam)
End Function
该钩子以下列方式安装在表单模块中:
SetHook App.ThreadID, Me.Text1.hWnd