VB.net中全局键盘钩子(Keyboard Hook)

来源:互联网 发布:超级视频软件 编辑:程序博客网 时间:2024/05/21 17:59

楔子

    网上关于Hook(钩子)的例子有很多,本文旨在简单且详细的介绍一下全局键盘的钩子,适合对钩子没有任何概念的人群,选用的IDE环境为VB.net和BCB6.0。

 

1.钩子的本质

 

    什么是钩子(Hook)?

    Windows的应用程序全部都是基于消息驱动的,而钩子,是一段用来处理系统消息的程序,是Windows消息的处理平台,从种类上可以分为多种,如键盘(WH_KEYBOARD),鼠标(WH_MOUSE)等,从监听的级别上又分为系统级和线程级,不过所谓的系统级其实也可以认为是线程级,稍后解释。

   

    系统钩子,监听当前系统中所有指定的消息。但是系统钩子会影响到系统中的所有应用程序的运行,因此需要将钩子函数放入到独立的动态链接库当中,也就是要写一个独立的DLL文件来完成。系统会自动将包含钩子回调函数的DLL映射到受钩子函数影响的所有进程的地址空间当中。

 

2.用到的Windows的API

    SetWindowsHookEx(int idHook, HooKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId)

    作用:

        安装钩子

    具体参数含义为:

        idHook:

            钩子的类型,如WH_KEYBOARD,就是想要监听什么消息

        lpfn:

            钩子过程的指针,就是回调函数,拦截到了消息之后处理函数的指针(函数在内存中的入口地址)

        hMod:

            应用程序实例的句柄。0表示自己

        dwThreadId:

            安装钩子的线程ID。0的话表示全局,即系统钩子,说到这里,提一下为什么说系统钩子实际上也是个线程够子,因为安装的钩子的线程ID是0,而Windows系统当中的线程ID为0的是谁?不错,就是桌面这个大窗口~,因为我们绝大部分的操作都是基于窗口消息的,而所有窗口的父窗口都是桌面这个大窗口,因此这个全局是相对与其他窗口程序的。

 

    UnHookWindowsHookEx(HHOOK hkk)

    作用:

            注销钩子

    具体参数含义为:

            hKK:

                钩子实例的名称

 

3.在VB.net中的实现

 

    实现需要三个步骤:

        (1)    了解什么是钩子

        (2)    编写独立的钩子的dll

        (3)    在VB.net中调用

    我们已经完成了第一个,下面说第二个步骤

    

    大家可以选用任何一种可以编写dll的工具,这里选用BCB6.0

    

    (1)新建一个DLL

    (2)代码如下:

 

DLL名称:

    KeyHook.dll

  1. #include <vcl.h>
  2. #include <windows.h>
  3. #include "windef.h"
  4. #pragma hdrstop
  5. #pragma argsused
  6. typedef LRESULT ( CALLBACK *HookProc)(int code, WPARAM w, LPARAM l);
  7. typedef  void (__stdcall  CALLBACK *Bakfun)(WPARAM w,KBDLLHOOKSTRUCT* k);
  8. //变量定义
  9. HookProc g_lpfnkeyboardProc;
  10. Bakfun g_bakProc;
  11. HINSTANCE hins=NULL;
  12. static HHOOK hkb=NULL;
  13. int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
  14. {
  15.         hins=hinst;
  16.         return 1;
  17. }
  18. //回调函数
  19. LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
  20. {
  21.         KBDLLHOOKSTRUCT* pstruct=(KBDLLHOOKSTRUCT*)lParam;
  22.         g_bakProc(wParam,pstruct); //回调函数,进入vb.net处理函数中
  23.         return CallNextHookEx( hkb, nCode, wParam, lParam );
  24. }
  25. //钩子启动函数
  26. extern "C"  __declspec(dllexportbool __stdcall  installhook(Bakfun lp)
  27. {
  28.         g_bakProc=lp;
  29.         hkb=SetWindowsHookEx(WH_KEYBOARD_LL,(HOOKPROC)KeyboardProc,hins,0);
  30.         return TRUE;
  31. }
  32. //卸载钩子函数
  33. extern "C"  __declspec(dllexportBOOL __stdcall  UnHook()
  34. {
  35.     BOOL unhooked = UnhookWindowsHookEx(hkb);
  36.     return unhooked;
  37. }

在VB.net中的代码

 

  1.     Public Declare Function installhook Lib "KeyHook.dll" (ByVal lp As HookProc) As Boolean
  2.     Public Declare Sub UnHook Lib "KeyHook.dll" ()
  3.     Public Delegate Sub HookProc(ByVal a As System.UIntPtr, ByVal ks As System.IntPtr)
  4.     Public Structure KBDLLHOOKSTRUCT
  5.         Dim vkCode As Integer
  6.         Dim scanCode As Integer
  7.         Dim flags As Integer
  8.         Dim time As Integer
  9.         Dim dwExtraInfo As Integer
  10.     End Structure
  11.     Public Enum KEYACTION
  12.         ACTION_KEYDOWN = WM_KEYDOWN
  13.         ACTION_KEYUP = WM_KEYUP
  14.         ACTION_SYSKEYDOWN = WM_SYSKEYDOWN
  15.         ACTION_SYSKEYUP = WM_SYSKEYUP
  16.     End Enum
  17.     Public Const WM_KEYDOWN = 
  18.     Public Const WM_KEYUP = 
  19.     Public Const WM_SYSKEYDOWN = 
  20.     Public Const WM_SYSKEYUP = 
  21.     Public Const DT_LEFT = 
  22.     Private Keys As Integer = 0
  23.     Public Sub HookProc1(ByVal a As System.UIntPtr, ByVal ks As System.IntPtr)
  24.         Dim kk As KBDLLHOOKSTRUCT
  25.         Dim KeyboardEvent As KEYACTION = CType(a.ToUInt32, KEYACTION)
  26.         If KeyboardEvent = KEYACTION.ACTION_KEYUP Then
  27.             kk = System.Runtime.InteropServices.Marshal.PtrToStructure(ks, kk.GetType())
  28.             Select Case kk.vkCode
  29.                 Case 88 'a的ASCII编码
  30.                     MessageBox.Show("a")
  31.             End Select
  32.         End If
  33.     End Sub

在主窗口当中

  1.     Private Sub Form1_Load(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles MyBase.Load
  2.         Static hkproc As HookProc
  3.         hkproc = AddressOf HookProc1
  4.         installhook(hkproc)
  5.     End Sub

 

运行程序即可,在任何窗口下按下键盘上的"A"键,都可以看到弹出一个对话框

 

PS:

    程序代码摘自http://www.ihome99.com/xiaowu/html/88/165788-32337.html

原创粉丝点击