2008年7月15日 星期二

Check Keyboard & Mouse Hook #3

打開VB新建一個項目,然後創建一個窗體和一個模塊,此程序已調試過,但是要注意的是在寫鉤子函數的過程,請在每次 RUN之前進行保存,這些API程序超越了VB的編譯環境,因為VB環境和這些API函數同屬系統級,因此它無法管理這些API,一旦出現問題,整個VB 環境會在毫無預知的情況下造成全線崩潰的局面。
正在裝載數據……

窗體中的代碼:窗體中的程序:
Option Explicit
Private Const WH_KEYBOARD_LL = 13&

Private Sub cmdExit_Click()
End
End Sub
Public Sub HookKeyboard()
KeyboardHandle = SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf KeyboardCallback, _
App.hInstance, 0&)
'WH_KEYBOARD_LL:攔截類型
'AddressOf KeyboardCallback:掛接函數鏈的首地址
'App.hInstance:程序本身的句柄
'0,表示全局攔截,意思就是攔截所有窗口下的鍵盤輸入
End Sub

Private Sub Form_KeyPress(KeyAscii As Integer)
If KeyAscii = 9 Then
MsgBox "你按下了TAB鍵!", vbOKOnly + vbInformation, "提示"
End If
If KeyAscii = 13 Then
MsgBox "你按下了ENTER鍵!", vbOKOnly + vbInformation, "提示"
End If
If KeyAscii = 97 Then
MsgBox "你按下了a鍵!", vbOKOnly + vbInformation, "提示"
End If
If KeyAscii = 65 Then
MsgBox "你按下了A鍵!", vbOKOnly + vbInformation, "提示"
End If
End Sub
Private Sub Form_Load()
Call HookKeyboard
End Sub
Private Sub Form_Unload(Cancel As Integer)
Call UnhookKeyboard
End Sub

模塊中的代碼:
Option Explicit
'通知Windows進行鉤子操作並定義鉤子函數
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
'idHook:攔截類型 lpfn:掛接函數鏈的首地址指針
'hmod:創建鉤子函數實體的句柄,即程序本身的句柄
'dwThreadId:為監控代碼,0表示全局監控,dwThreadId用於線程鉤子VB中可以設置為App.ThreadID。

Public Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
'釋放鉤子
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, _
pSource As Any, ByVal cb As Long)
'將內存裡的某一塊數據pSource拷貝到另一個地址pDest,cb表示拷貝內容的字節大小

Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, _
ByVal nCode As Long, ByVal wParam As Long, _
ByVal lParam As Long) As Long
'掛鉤函數攔截了某條消息後,由CallNextHookEx決定是否將這些消息送還給Windows系統

Private Type KBDLLHOOKSTRUCT '鍵盤鉤子的結構體
vkCode As Long '虛擬鍵碼
scanCode As Long '掃瞄碼
flags As Long '功能鍵狀態
time As Long
dwExtraInfo As Long
End Type

Public KeyboardHandle As Long '鍵盤鉤子函數句柄
Private Const HC_ACTION = 0
Private Const LLKHF_EXTENDED = &H1
Private Const LLKHF_INJECTED = &H10
Private Const LLKHF_ALTDOWN = &H20
Private Const LLKHF_UP = &H80
Public Const VK_A = &H41
Public Const VK_ENTER = &HD
Public Const VK_TAB = &H9
Public Const VK_CONTROL = &H11
Public Const VK_ESCAPE = &H1B
Public Const VK_DELETE = &H2E

'鉤子函數的核心
Public Function KeyboardCallback(ByVal Code As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
'Code 表示攔截層次,之前我們已經說過,如果Code為0,則攔截所有窗口的鍵盤輸入
'wParam 表示是何種Windows消息
'lParam表示某條Windows消息的具體內容的指針,它實際指向存儲那個內容的內存地址

Static Hookstruct As KBDLLHOOKSTRUCT '定義一個局部靜態結構體實例
If (Code = HC_ACTION) Then '鑑別Windows的消息來源
Call CopyMemory(Hookstruct, ByVal lParam, Len(Hookstruct))
If (IsHooked(Hookstruct)) Then '過濾消息
KeyboardCallback = 1
Exit Function
End If
End If
KeyboardCallback = CallNextHookEx(KeyboardHandle, Code, wParam, lParam)
'將消息釋放,用CallNextHookEx交還給系統
End Function
Public Function IsHooked(ByRef Hookstruct As KBDLLHOOKSTRUCT) As Boolean
'If (KeyboardHook Is Nothing) Then
If KeyboardHandle = 0 Then
IsHooked = False
Exit Function
End If
'有時候CopyMemory也會發生意想不到的事情,所以,當KeyboardHook = Nothing (無值)的情況下,退出,略過該函數,以防不可預知的錯誤。
If (Hookstruct.vkCode = VK_TAB) And _
CBool(Hookstruct.flags And _
LLKHF_ALTDOWN) Then '屏蔽ALT+TAB鍵組合
IsHooked = True
Exit Function
End If
'以上攔截了Alt+Tab的鍵盤組合,並將IsHooked返回True(就是1),表示本次按鍵確實符合了過濾原則,應該吞吃掉。
If (Hookstruct.vkCode = VK_ENTER) Then '屏蔽ENTER鍵
IsHooked = True
Exit Function
End If
If (Hookstruct.vkCode = VK_A) Then '屏蔽A和a鍵
IsHooked = True
Exit Function
End If
End Function

Public Sub UnhookKeyboard() '釋放鉤子函數
'If (Hooked) Then
Call UnhookWindowsHookEx(KeyboardHandle)
'End If
End Sub

沒有留言: