人人IT網

人人IT網

當前位置: 主頁 > 操作系統 > Windows >

VB無所不能之三:VB截獲Windows消息的鉤子

時間:2016-10-07 00:37來源:Internet 作者:Internet 點擊:
VB無所不能之三:VB截獲Windows消息的鉤子 ――作者:钟聲 博客地址:http://useway.blog.51cto.com       VB一直被認
VB無所不能之三:VB截獲Windows消息的鉤子
――作者:钟聲
 
    VB一直被認为是一個可以通過簡單的方法,完成Windows界面應用程序的一個語言。對Windows系統方面的編程似乎首先想到的絕對不是VB,而大部分程序員想到的一定是VC。我們今天就介紹一種用VB截獲Windows全局消息的方法。
   
    一、Windows全局消息介紹
    我不喜歡用非常晦澀的語言來介紹一個簡單的事物,因此,我想在本篇文章中就用通俗的語言來解釋這個概念吧。
    什麼是Windows全局消息呢?
    例如:鼠標在自定義的窗口中移動的位置,我們可以通過這個Form中的相關方法獲取,然而,如果鼠標並沒有在自己的Form中移動又該怎麼獲得其位置呢?
    再例如:鍵盤的敲擊動作,在別的地方敲擊鍵盤,並沒有在自己的Form中敲擊鍵盤,怎麼才能獲得按鍵的具體鍵值呢?
    對單片機有了解的朋友都知道,鼠標和鍵盤的操作都是利用的是“中斷”觸發事件來完成的,那麼當系統“中斷”的時候,就會發出消息给操作系統,而這些消息就是Windows全局消息。
 
    二、鉤子簡介
    鉤子是通過英文Hook翻譯過來的,所謂的鉤子就是在Windows全局消息傳遞到操作系統之前進行截獲,經過處理後再傳遞给操作系統或者其他鉤子的程序。
    想想看,鉤子聽起來像什麼程序?
    對沒錯,黑客程序,木馬程序,都是通過鉤子的方法獲取鼠標鍵盤的相應操作信息,還獲取密碼或其他有用信息的。
    但是,鉤子其本身並不是病毒,而是提供给我們程序員一種獲取操作系統動作的一個方法,這個方法有時候非常有用,可以非常方便的開發針對操作系統的優質程序。
 
    三、消息種類
 
    1、WH_CALLWNDPROC和WH_CALLWNDPROCRET
    這兩種消息是發送到窗口過程的消息,系統在消息發送到接收窗口過程之前調用WH_CALLWNDPROC,並且在窗口過程處理完消息之後調用WH_CALLWNDPRO 。
 
    2、WH_CBT   
    它是激活,建立,銷毀,最小化,最大化,移動,改變尺寸等窗口事件;
    完成系統指令;來自系統消息隊列中的移動鼠標,鍵盤事件;
    設置輸入焦點事件;同步系統消息隊列事件。
 
    3、WH_KEYBOARD
    WM_KEYDOWN     監視     WM_KEYUP
 
    4、WH_KEYBOARD_LL
    監視輸入到線程消息隊列中的鍵盤消息
 
    5、WH_MOUSE
    監視輸入到消息隊列中的鼠標消息
 
    6、WH_MOUSE_LL
    監視輸入到線程消息隊列中的鼠標消息

    四、鉤子類型
   
    1)    線程鉤子:監視指定線程的事件消息。    
    2)    系統鉤子:監視系統中的所有線程的事件消息。
 
    VB只能設定線程鉤子,因为系統鉤子會影響系統中所有的應用程序,所以鉤子函數必須放在獨立的動態鏈接庫(DLL)中才能做到。
 
   五、VB建立鉤子的方法步驟
 
   步驟1:掛鉤
 
   掛鉤是第一步,目的是1,告訴操作系統我要監聽什麼消息,2是告訴操作系統得到消息後調用什麼回調函數。
 
   掛鉤的方法:
   例如:
   Private Const WH_MOUSE_LL As Long = 14
   Private hHook As Long
   ......
   hHook = SetWindowsHookEx(WH_MOUSE_LL, AddressOf HookProc, App.hInstance, 0)
 
   第一個参數:告訴操作系統,我要掛的是一個鼠標監聽鉤子。
   第二個参數:告訴操作系統,我的回調函數是HookProc,AddressOf的作用是得到HookProc這個函數的地址。
 
   步驟二:回調函數的編寫
 
   Public Function HookProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lparam As Long) As Long
    Dim typMHS As MSLLHOOKSTRUCT, pt As POINTAPI
    If wParam = WM_MOUSEMOVE Then
        Call CopyMemory(typMHS, ByVal lparam, LenB(typMHS))
        pt = typMHS.pt
        'If PtInRect(hRT, pt.x, pt.y) <> 0 Then
        '    HookProc = 1 '取消原本要完成的�作
        'Else
            Form1.Caption = "mouse Cursor at " + CStr(pt.x) + "," + CStr(pt.y)
            HookProc = 0 '令待完成的�作��完成
        'End If
    End If
   
    If wParam = WM_LBUTTONDOWN Then
       Debug.Print "l"
    End If
   
    If wParam = WM_RBUTTONDOWN Then
       Debug.Print "r"
    End If
   
    'If nCode < 0 Then
       HookProc = CallNextHookEx(hHook, nCode, wParam, lparam)
    '   Exit Function
    'End If
   
End Function
 
    注意一:回調函數的格式
    Public Function HookProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lparam As Long) As Long
     nCode:鉤子的句柄
     wParam,lParam:包含了攔截到的消息內容,同样它也與Hook的種類和nCode的值不同而不同。比如在鍵盤鉤子(KeyBoard)中,wParam則是按鍵返回碼。如果是鼠標事件,那麼包含的鼠標的位置信息和按鍵信息。
 
    注意二:在回調函數結束的時候,需要增加一個CallNextHookEx把消息再傳遞给下一個鉤子或者操作系統。
    這個也很好理解,你截獲消息以後,並不是要把這個消息真的截獲,而只是想進行相應處理,然後再把消息傳遞给下一個接棒者。
 
    步驟三:釋放鉤子
    在程序結束後,需要把鉤子摘掉,否則,一直會監聽系統的消息。
 
    Call UnhookWindowsHookEx(hHook)
 
    六、完整的VB鉤子程序
 
模塊代碼:
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
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 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 WH_MOUSE_LL As Long = 14
Private Const WM_MOUSEMOVE = &H200
Private Const WM_LBUTTONDOWN = &H201
Private Const WM_LBUTTONUP = &H202
Private Const WM_LBUTTONDBLCLK = &H203
Private Const WM_RBUTTONDOWN = &H204
Private Const WM_RBUTTONUP = &H205
Private Const WM_RBUTTONDBLCLK = &H206
Private Const WM_MBUTTONDOWN = &H207
Private Const WM_MBUTTONUP = &H208
Private Const WM_MBUTTONDBLCLK = &H209
Private Const WM_MOUSEACTIVATE = &H21
Private Const WM_MOUSEFIRST = &H200
Private Const WM_MOUSELAST = &H209
Private Const WM_MOUSEWHEEL = &H20A   '以上是鼠標的各個值
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 hHook As Long
Public Sub EnableHook()
    If hHook = 0 Then
       hHook = SetWindowsHookEx(WH_MOUSE_LL, AddressOf HookProc, App.hInstance, 0)
    End If
End Sub
Public Sub FreeHook()
    If hHook <> 0 Then
       Call UnhookWindowsHookEx(hHook)
       hHook = 0
    End If
End Sub
Public Function HookProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lparam As Long) As Long
    Dim typMHS As MSLLHOOKSTRUCT, pt As POINTAPI
    If wParam = WM_MOUSEMOVE Then
        Call CopyMemory(typMHS, ByVal lparam, LenB(typMHS))
        pt = typMHS.pt
        Debug.Print "mouse Cursor at " + CStr(pt.x) + "," + CStr(pt.y)
    End If
   
    If wParam = WM_LBUTTONDOWN Then
       Debug.Print "l"
    End If
   
    If wParam = WM_RBUTTONDOWN Then
       Debug.Print "r"
    End If
   
    HookProc = CallNextHookEx(hHook, nCode, wParam, lparam)
 
End Function

 
 
窗口代碼:
 
Private Sub Form_Load()
    EnableHook
End Sub
Private Sub Form_Unload(Cancel As Integer)
    FreeHook
End Sub
 

本文出自 ““純真”程序員俱樂部” 博客,請務必保留此出處http://go.rritw.com/useway.blog.51cto.com/736087/176913


From:51CTO
頂一下
(0)
0%
踩一下
(0)
0%
------分隔線----------------------------
發表評論
請自覺遵守互聯網相關的政策法規,嚴禁發布色情、暴力、反動的言論。
評價:
表情:
驗證碼:點擊我更換圖片
欄目列表
推薦內容