钩子函数是Windows消息处理机制的一部分,通过设置“钩子”,应用程序可以在系统级对所有消息、事件进行过滤,访问在正常情况下无法访问的消息。钩子的本质是一段用以处理系统消息的程序,通过系统调用,把它挂入系统。
钩子函数
作用
WINDOWS的
钩子函数可以认为是WINDOWS的主要特性之一。利用它们,您可以捕捉您自己进程或其它进程发生的事件。通过“钩挂”,您可以给WINDOWS一个处理或过滤事件的
回调函数,该函数也叫做“
钩子函数”,当每次发生您感兴趣的事件时,WINDOWS都将调用该函数。
类型
钩子分两种, 一种是系统级的全局钩子; 一种是线程级的钩子.全局钩子函数需要定义在 DLL 中, 线程级的钩子开始比较简单.
其实钩子函数就三个:
在线程级的钩子中经常用到 GetCurrentThreadID 函数来获取当前线程的 ID
简介
系统范围的 将捕捉系统中所有进程将发生的事件消息。 当您创建一个
钩子时,WINDOWS会先在内存中创建一个
数据结构,该数据结构包含了钩子的相关信息,然后把该
结构体加到已经存在的钩子链表中去。新的
钩子将加到老的前面。当一个事件发生时,如果您安装的是一个局部
钩子,您进程中的钩子函数将被调用。如果是一个远程
钩子,系统就必须把钩子函数插入到其它进程的
地址空间,要做到这一点要求钩子函数必须在一个动态链接库中,所以如果您想要使用远程钩子,就必须把该钩子函数放到动态链接库中去。
特例
当然有两个例外:工作日志
钩子和工作日志回放钩子。这两个
钩子的钩子函数必须在安装钩子的线程中。原因是:这两个
钩子是用来监控比较底层的硬件事件的,既然是记录和回放,所有的事件就当然都是有先后次序的。所以如果把
回调函数放在DLL中,输入的事件被放在几个线程中记录,所以我们无法保证得到正确的次序。
解决方法
故解决的办法是:把
钩子函数放到单个的线程中,譬如安装钩子的线程。
WH_CALLWNDPROC 当调用SendMessage时
WH_CALLWNDPROCRET 当SendMessage的调用返回时
WH_GETMESSAGE 当调用GetMessage 或 PeekMessage时
WH_KEYBOARD 当调用GetMessage 或 PeekMessage 来从消息队列中查询WM_KEYUP 或 WM_KEYDOWN 消息时
WH_MOUSE 当调用GetMessage 或 PeekMessage 来从消息队列中查询鼠标事件消息时
WH_HARDWARE 当调用GetMessage 或 PeekMessage 来从
消息队列种查询非鼠标、键盘消息时
WH_MSGFILTER 当对话框、菜单或滚动条要处理一个消息时。该
钩子是局部的。它是为那些有自己的消息处理过程的控件对象设计的。
WH_SYSMSGFILTER 和WH_MSGFILTER一样,只不过是系统范围的
WH_JOURNALRECORD 当WINDOWS从硬件队列中获得消息时
WH_JOURNALPLAYBACK 当一个事件从系统的硬件输入队列中被请求时
WH_SHELL 当关于WINDOWS外壳事件发生时,譬如任务条需要重画它的按钮.
WH_CBT 当基于计算机的训练(CBT)事件发生时
WH_FOREGROUNDIDLE 由WINDOWS自己使用,一般的
应用程序很少使用
附:如何使用
钩子函数(接收到字母A按下时,
窗体由最小化弹出的完整的代码)
(ByVal hHook As Long, _
ByVal nCode As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
Public Declare Function
UnhookWindowsHookEx(ByVal hHook As Long) As Long
(ByVal idHook As Long, _
ByVal lpfn As Long, _
ByVal hmod As Long, _
ByVal dwThreadId As Long) As Long
Public Const WH_KEYBOARD = 2
Public Const KEY_WINSTART = 91
Public Const KEY_WINMENU = 93
Global hHook As Long
Public Function
KeyboardProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If nCode >= 0 Then
If wParam = KEY_WINMENU Or wParam = KEY_WINSTART Then
If (lParam And &HC0000000) = 0 Then
Exit Function
End If
End If
End If
KeyboardProc = CallNextHookEx(hHook, nCode, wParam, lParam)
End Function
Option Explicit
Private Sub Command1_Click()
form2.Show 1
End Sub
Private Sub form_Load()
hHook = SetWindowsHookEx(WH_KEYBOARD, AddressOf
KeyboardProc, 0&, App.ThreadID)
Me.Show
End Sub
Private Sub form_Unload(Cancel As Integer)
End Sub