VB6之HOOK技术

代码背景,自身程序的窗口上有一个TextBox,Hook住WH_CALLWNDPROC用来截获EN_CHNAGE即文本变更的消息。

*这个其实用SetWindowLong和CallWindowProc也能做到,原理是一样的就是预处理窗口消息。

Form1.frm

Private Sub Command1_Click()
    hHook = SetWindowsHookEx(WH_CALLWNDPROC, AddressOf CallBackHookProc, App.hInstance, App.ThreadID)
    Debug.Print hHook
End Sub

Private Sub Command2_Click()
    Call UnhookWindowsHookEx(hHook)
End Sub

Module1.bas

Public 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
Public Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Public Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, _
    ByVal nCode As Long, _
    ByVal wParam As Long, _
    lParam As Any) As Long
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, _
    Source As Any, _
    ByVal Length As Long)
Public Const WH_CALLWNDPROC = 4
Public Const WM_COMMAND = &H111
Public Const EN_CHANGE = &H300
Public Type CWPSTRUCT
        lParam As Long
        wParam As Long
        message As Long
        hwnd As Long
End Type
Public Const HC_ACTION = 0
Public hHook As Long

Public Function CallBackHookProc(ByVal nCode As Long, _
    ByVal wParam As Long, _
    ByVal lParam As Long) As Long
    
    If nCode = HC_ACTION Then
        Dim Msg As CWPSTRUCT
        Call CopyMemory(Msg, ByVal lParam, Len(Msg))
        If Msg.message = WM_COMMAND Then
            If (Msg.wParam And &HFFFF0000) / &H10000 = EN_CHANGE Then
                Debug.Print "GOTCHA"
            End If
        End If
    End If
    
    CallBackHookProc = CallNextHookEx(hHook, nCode, wParam, lParam)
End Function

运行代码,点击Command1后挂载HOOK,当TextBox里的文本改变时,会打印出“GOTCHA”。

由于,我窗体上只有一个TextBox是Edit控件,所以我在代码中就没有判断消息源(hwnd)是不是TextBox。