本文引自。感谢原创!http://www.jb51.cc/article/p-osrvlayo-bdd.html
VB无所不能之三:VB截获Windows消息的钩子
——作者:钟声
VB一直被认为是一个可以通过简单的方法,完成Windows界面应用程序的一个语言。对Windows系统方面的编程似乎首先想到的绝对不是VB,而大部分程序员想到的一定是VC。我们今天就介绍一种用VB截获Windows全局消息的方法。
一、Windows全局消息介绍
我不喜欢用非常晦涩的语言来介绍一个简单的事物,因此,我想在本篇文章中就用通俗的语言来解释这个概念吧。
什么是Windows全局消息呢?
对单片机有了解的朋友都知道,鼠标和键盘的操作都是利用的是“中断”触发事件来完成的,那么当系统“中断”的时候,就会发出消息给操作系统,而这些消息就是Windows全局消息。
二、钩子简介
钩子是通过英文Hook翻译过来的,所谓的钩子就是在Windows全局消息传递到操作系统之前进行截获,经过处理后再传递给操作系统或者其他钩子的程序。
想想看,钩子听起来像什么程序?
三、消息种类
1、WH_CALLWNDPROC和WH_CALLWNDPROCRET
2、WH_CBT
它是激活,建立,销毁,最小化,最大化,移动,改变尺寸等窗口事件;
完成系统指令;来自系统消息队列中的移动鼠标,键盘事件;
设置输入焦点事件;同步系统消息队列事件。
3、WH_KEYBOARD
WM_KEYDOWN 监视 WM_KEYUP
4、WH_KEYBOARD_LL
监视输入到线程消息队列中的键盘消息
5、WH_MOUSE
监视输入到消息队列中的鼠标消息
6、WH_MOUSE_LL
监视输入到线程消息队列中的鼠标消息
四、钩子类型
1) 线程钩子:监视指定线程的事件消息。
2) 系统钩子:监视系统中的所有线程的事件消息。
2) 系统钩子:监视系统中的所有线程的事件消息。
五、VB建立钩子的方法步骤
步骤1:挂钩
挂钩的方法:
例如:
Private Const WH_MOUSE_LL As Long = 14
Private hHook As Long
......
hHook = SetWindowsHookEx(WH_MOUSE_LL,AddressOf HookProc,App.hInstance,0)
第一个参数:告诉操作系统,我要挂的是一个鼠标监听钩子。
步骤二:回调函数的编写
Public Function HookProc(ByVal nCode As Long,ByVal wParam As Long,ByVal lparam As Long) As Long
Dim typMHS As MSLLHOOKSTRUCT,pt As POINTAPI
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
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 lparam As Long) As Long
nCode:钩子的句柄
wParam,lParam:包含了拦截到的消息内容,同样它也与Hook的种类和nCode的值不同而不同。比如在键盘钩子(KeyBoard)中,wParam则是按键返回码。如果是鼠标事件,那么包含的鼠标的位置信息和按键信息。
wParam,lParam:包含了拦截到的消息内容,同样它也与Hook的种类和nCode的值不同而不同。比如在键盘钩子(KeyBoard)中,wParam则是按键返回码。如果是鼠标事件,那么包含的鼠标的位置信息和按键信息。
这个也很好理解,你截获消息以后,并不是要把这个消息真的截获,而只是想进行相应处理,然后再把消息传递给下一个接棒者。
步骤三:释放钩子
在程序结束后,需要把钩子摘掉,否则,一直会监听系统的消息。
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,lparam As Any) As Long
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,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 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
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
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,0)
End If
End Sub
If hHook = 0 Then
hHook = SetWindowsHookEx(WH_MOUSE_LL,0)
End If
End Sub
Public Sub FreeHook()
If hHook <> 0 Then
Call UnhookWindowsHookEx(hHook)
hHook = 0
End If
End Sub
If hHook <> 0 Then
Call UnhookWindowsHookEx(hHook)
hHook = 0
End If
End Sub
Public Function HookProc(ByVal nCode As Long,ByVal lparam As Long) As Long
Dim typMHS As MSLLHOOKSTRUCT,pt As POINTAPI
Dim typMHS As MSLLHOOKSTRUCT,pt As POINTAPI
If wParam = WM_MOUSEMOVE Then
Call CopyMemory(typMHS,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,lparam)
End Function
Call CopyMemory(typMHS,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,lparam)
End Function
窗口代码:
Private Sub Form_Load()
EnableHook
End Sub
EnableHook
End Sub
Private Sub Form_Unload(Cancel As Integer) FreeHook End Sub