훅에도 여러 종류가 있지만
전역  훅을 사에도
어떤 타입의 훅으 사용하느냐에 따라 훅 타입이 있으며
이들 훅은 각 타입에 따라 훅체인을 이룬다
훅체인은 각 훅 프로시저(훅으 처리하는 프로시저)를 고리처럼 묶어둔 것을 말한다. 훅 배열이라고 할가.

이 훅체인에 훅 프로시저를 추가하기 위해서는 용하기 SetWindowsHookEx를 사용하며
훅체인에서 훅 프로시저를 제거하기 위해선는 UnhookWindowsHookEx를 사용한다.

훅 타입에는 다음과 같은 타입이 있다.

WH_CALLWNDPROC 4 윈도우 프로시저 후킹
WH_CALLWNDPROCRET 12
WH_CBT 5
WH_DEBUG 9
WH_FOREGROUNDIDLE 11
WH_GETMESSAGE 3 GetMsgProc 메세지 큐에 메세지를 감시한다
WH_JOURNALPLAYBACK 1
WH_JOURNALRECORD 0
WH_KEYBOARD 2
WH_KEYBOARD_LL 13 LowLevelKeyboardProc 저수준 키보드 훅을 한다
WH_MOUSE 7 마우스 메세지
WH_MOUSE_LL 14 LowLevelMouseProc 마우스 저수준 훅을 한다
WH_MSGFILTER -1
WH_SHELL 10
WH_SYSMSGFILTER 6

훅체인에 훅 프로시저를 추가하여 메세지를 후킹한다
● 선언 Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long

● 인수

idHook ━ 후킹할 메세지 타입
lpfn ━ 후킹 메세지가 전달될 프로시저 주소(AddressOf testHook) 하면 함수의(일반 모듈에 선언된) 주소를 얻을수 있다. 훅에 사용할 함수 형식은 함수명(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long, 각 인수의 값을 훅타입에 따라 의미가 다르다
hmod ━ 인스턴스 핸들로, lpfn에 전달된 프로시저를 포함한는 DLL의 인스턴스 핸들, 만약 DLL에 프로시적아 있다면 DLL의 인스턴스 핸들을 넘겨주면 되고, 그렇치 않다면 응용프로그램의 핸들(App.Instarance)을 넘겨주면 된다
dwThreadId ━ 쓰레드 식별자, 0이면 호출된 쓰레드를 나타낸다.

반환
성공 ━ 설치된 훅 핸들값
실패 ━ 0

다음은 마우스를 훅한 예이다



다음은 소스이다
' 폼 소스
' 저수준 마우스 전역 훅
Option Explicit ' 모든 변수는 선언된 뒤에 사용할 수 있다.

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 ' 훅체인에 훅프로시저를 선두에 끼워넣는다, 성공하면 훅프로시저의 핸들을 복귀한다.
Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long ' 훅체인에서 훅 핸들이 나타내는 훅 프로시저를 제거한다.
Private Const WH_MOUSE_LL = 14

Private hhkLowLevelMouse As Long  ' 훅 설치가 완료되는경우, 그 훅을 나타내는 핸들

Private Sub Form_Load()
    Set WindowMessage = Label1
    hhkLowLevelMouse = SetWindowsHookEx(WH_MOUSE_LL, AddressOf LowLevelMouseProc, App.hInstance, 0)
End Sub

Private Sub Form_Unload(Cancel As Integer)
    If hhkLowLevelMouse = 0 Then Exit Sub
    UnhookWindowsHookEx hhkLowLevelMouse ' 훅을 체인에서 훅 제거한다.
    hhkLowLevelMouse = 0
End Sub

'모듈 소스
Option Explicit ' 모든 변수는 선언된 뒤에 사용할 수 있다.

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long) ' 메모리 내용을 복사한다.
Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal nCode As Long, ByVal wParam As Long, lParam As Any) As Long ' 훅체인에서 다음 훅프로시저를 호출한다.

Private Const HC_ACTION = 0 ' 메세지의 일반적인 상태

Private Const WM_LBUTTONDOWN = &H201
Private Const WM_LBUTTONUP = &H202
Private Const WM_MBUTTONDOWN = &H207
Private Const WM_MBUTTONUP = &H208
Private Const WM_MOUSEMOVE = &H200
Private Const WM_MOUSEWHEEL = &H20A
Public Const WM_RBUTTONDOWN = &H204
Private Const WM_RBUTTONUP = &H205

Private Type POINTAPI
    x As Long
    y As Long
End Type

Private Type MSLLHOOKSTRUCT
    pt          As POINTAPI
    mouseData   As Long
    flags       As Long
    time        As Long
    dwExtraInfo As Long
End Type

Public WindowMessage As Label

Dim p As MSLLHOOKSTRUCT

' 키보드 훅 프로시저
Public Function LowLevelMouseProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    If (nCode = HC_ACTION) Then
        Select Case wParam
            Case WM_MOUSEMOVE
                WindowMessage.Caption = "마우스가 움직였읍니다"
            Case WM_LBUTTONDOWN
                WindowMessage.Caption = "마우스가 왼쪽 버튼이 눌렸읍니다."
            Case WM_LBUTTONUP
                WindowMessage.Caption = "마우스가 왼쪽 버튼이 눌렸다 놓였읍니다."
            Case WM_RBUTTONDOWN
                WindowMessage.Caption = "마우스가 오른쪽 버튼이 눌렸읍니다."
            Case WM_RBUTTONUP
                WindowMessage.Caption = "마우스가 오른쪽 버튼이 눌렸다 놓였읍니다."
            Case WM_MOUSEWHEEL
                WindowMessage.Caption = "마우스가 휠이 움직였읍니다."
            Case WM_MBUTTONDOWN
                WindowMessage.Caption = "마우스가 가운데 버튼이 눌렸읍니다."
            Case WM_MBUTTONUP
                WindowMessage.Caption = "마우스가 가운데 버튼이 눌렸다 놓였읍니다."
            Case Else
                Debug.Print Hex(wParam)
        End Select
    End If
    CopyMemory p, ByVal lParam, Len(p)
    WindowMessage.Caption = WindowMessage.Caption & " " & p.pt.x & " " & p.pt.y
    LowLevelMouseProc = CallNextHookEx(0, nCode, wParam, ByVal lParam) ' 훅체인에 다음 훅 프로시저를 호출한다.
End Function


CallNextHookEx는 훅체인에서 다음 훅 프로시저를 호출하게 된다

+ Recent posts