杨壹琳的回答:
Hook简介 Hook这个东西有时令人又爱又怕,Hook是用来拦截系统某些讯息之用,例如说,我们想 让系统不管在什么地方只要按个Ctl-B便执行NotePad,或许您会使用Form的KeyPreview ,设定为True,但在其他Process中按Ctl-B呢?那就没有用,这是就得设一个Keyboard Hook来拦截所有Key in的键;再如:MouseMove的Event只在该Form或Control上有效,如果希望在Form的外面也能得知Mouse Move的讯息,那只好使用Mouse Hook来栏截Mouse 的讯息。再如:您想记录方才使用者的所有键盘动作或Mosue动作,以便录巨集,那就 使用JournalRecordHook,如果想停止所有Mosue键盘的动作,而放(执行)巨集,那就 使用JournalPlayBack Hook;Hook呢,可以是整个系统为范围(Remote Hook),即其他 Process的动作您也可以拦截,也可以是LocalHook,它的拦截范围只有Process本身。 Remote Hook的Hook Function要在.Dll之中,Local Hook则在.Bas中。 在VB如何设定Hook呢?使用SetWindowsHookEx() 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代表是何种Hook,有以下几种 Public Const WH_CALLWNDPROC = 4 Public Const WH_CALLWNDPROCRET = 12 Public Const WH_CBT = 5 Public Const WH_DEBUG = 9 Public Const WH_FOREGROUNDIDLE = 11 Public Const WH_GETMESSAGE = 3 Public Const WH_HARDWARE = 8 Public Const WH_JOURNALPLAYBACK = 1 Public Const WH_JOURNALRECORD = 0 Public Const WH_KEYBOARD = 2 Public Const WH_MOUSE = 7 Public Const WH_MSGFILTER = (-1) Public Const WH_SHELL = 10 Public Const WH_SYSMSGFILTER = 6 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自己使用,一般的应用程序很少使用 WH_DEBUG 用来给钩子函数除错 lpfn代表Hook Function所在的Address,这是一个CallBack Fucnction,当挂上某个 Hook时,我们便得定义一个Function来当作某个讯息产生时,来处理它的Function ,这个Hook Function有一定的叁数格式 Private Function HookFunc(ByVal ncode As Long, _ ByVal wParam As Long, _ ByVal lParam As Long) As Long nCode 代表是什么请况之下所产生的Hook,随Hook的不同而有不同组的可能值 wParam lParam 传回值则随Hook的种类和nCode的值之不同而不同。 因这个叁数是一个 Function的Address所以我们固定将Hook Function放在.Bas中, 并以AddressOf HookFunc传入。至于Hook Function的名称我们可以任意给定,不一 定叫 HookFunc hmod 代表.DLL的hInstance,如果是Local Hook,该值可以是Null(VB中可传0进去), 而如果是Remote Hook,则可以使用GetModuleHandle(".dll名称")来传入。 dwThreadId 代表执行这个Hook的ThreadId,如果不设定是那个Thread来做,则传0(所以 一般来说,Remote Hook传0进去),而VB的Local Hook一般可传app.ThreadId进去 值回值如果SetWindowsHookEx()成功,它会传回一个值,代表目前的Hook的Handle, 这个值要记录下来。 因为A程式可以有一个System Hook(Remote Hook),如KeyBoard Hook,而B程式也来设一 个Remote的KeyBoard Hook,那么到底KeyBoard的讯息谁所拦截?答案是,最后的那一个 所拦截,也就是说A先做keyboard Hook,而后B才做,那讯息被B拦截,那A呢?就看B的 Hook Function如何做。如果B想让A的Hook Function也得这个讯息,那B就得呼叫 CallNextHookEx()将这讯息Pass给A,于是产生Hook的一个连线。如果B中不想Pass这讯息 给A,那就不要呼叫CallNextHookEx()。 Declare Function CallNextHookEx Lib "user32" _ (ByVal hHook As Long, _ ByVal ncode As Long, _ ByVal wParam As Long, _ lParam As Any) As Long hHook值是SetWindowsHookEx()的传回值,nCode, wParam, lParam则是Hook Procedure 中的三个叁数。 最后是将这Hook去除掉,请呼叫UnHookWindowHookEx() Declare FunctionUnhookWindowsHookExLib "user32" (ByVal hHook As Long) As Long hHook便是SetWindowsHookEx()的传回值。此时,以上例来说,B程式结束Hook,则换A可 以直接拦截讯息。 KeyBoard Hook的范例 Hook Function的三个叁数 nCode wParam lParam 传回值 HC_ACTION 表按键Virtual Key 与WM_KEYDOWN同 若讯息要被处理传0 或 反之传1 HC_NOREMOVE Public hHook As Long Public Sub UnHookKBD() If hnexthookproc <;>; 0 Then UnhookWindowsHookExhHook hHook = 0 End If End Sub Public Function EnableKBDHook() If hHook <;>; 0 Then Exit Function End If hHook = SetWindowsHookEx(WH_KEYBOARD, AddressOf MyKBHFunc, App.hInstance, App.ThreadID) End Function Public Function MyKBHFunc(ByVal iCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long MyKBHFunc = 0 "表示要处理这个讯息 If wParam = vbKeySnapshot Then "侦测 有没有按到PrintScreen键 MyKBHFunc = 1 "在这个Hook便吃掉这个讯息 End If Call CallNextHookEx(hHook, iCode, wParam, lParam) "传给下一个Hook End Function 只要将上面代码放在VB的模块中,用标准VB程序就可以了,当运行该程序后,就能拦截所有键盘操作。
彩虹的微笑的回答: