0

朋友们好,我想监控窗体上的IP地址控件(由CreateWindowEx创建)的输入事件。我使用API​​ SetWindowsHookEx挂钩WH_GETMESSAGE消息,但现在我不能将输入消息作为(MSG)lParam-> message = WM_NULL 就像在 C 中一样,所以我需要你的帮助,朋友们。你能给我解决方案吗?

这是代码:

Private Function GetMsgProc(ByVal nCode As Long, ByVal wParam As Long, ByRef lParam As Long) As Long
CopyMemory p, ByVal lParam, LenB(p)
If p.message = WM_RBUTTONDOWN And GetParent(p.hWnd) = lngHWNDCtl Then
    GetMsgProc = 0
Else
    GetMsgProc = CallNextHookEx(hHook, nCode, wParam, ByVal lParam)
End If
End Function

Public Sub SetHook(ByVal lngThread As Long, lngHWND As Long, bFlag As Boolean)
If bFlag Then
    lngHWNDCtl = lngHWND
    hHook = SetWindowsHookEx(WH_GETMESSAGE, AddressOf GetMsgProc, 0, lngThread)
Else
   If hHook Then UnhookWindowsHookEx hHook
End If
End Sub
4

1 回答 1

2
  1. 跳过对过滤器函数的调用CallNextHookEx通常GetMsgProc是一个坏主意。如果您这样做,则不会调用链中的其他过滤器函数。也许,在开发机器上没有,但是“在野外”会有其他安装了钩子的应用程序。如果您阻止调用它们的过滤器函数,这些应用程序将出现异常行为。
  2. 您可能不想分析只是从队列中偷看但没有从队列中删除的消息。为已从队列中删除的消息GetMsgProc调用。wParam = PM_REMOVE
  3. 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
于 2013-04-02T21:09:50.437 回答