欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C#实现可捕获几乎所有键盘鼠标事件的钩子类完整实例

程序员文章站 2022-05-28 18:45:27
本文实例讲述了c#实现可捕获几乎所有键盘鼠标事件的钩子类。分享给大家供大家参考,具体如下: using system; using system.text;...

本文实例讲述了c#实现可捕获几乎所有键盘鼠标事件的钩子类。分享给大家供大家参考,具体如下:

using system;
using system.text;
using system.runtime.interopservices;
using system.reflection;
using system.windows.forms;
namespace mousekeyboardlibrary
{
  /// <summary>
  /// abstract base class for mouse and keyboard hooks
  /// </summary>
  public abstract class globalhook
  {
    #region windows api code
    [structlayout(layoutkind.sequential)]
    protected class point
    {
      public int x;
      public int y;
    }
    [structlayout(layoutkind.sequential)]
    protected class mousehookstruct
    {
      public point pt;
      public int hwnd;
      public int whittestcode;
      public int dwextrainfo;
    }
    [structlayout(layoutkind.sequential)]
    protected class mousellhookstruct
    {
      public point pt;
      public int mousedata;
      public int flags;
      public int time;
      public int dwextrainfo;
    }
    [structlayout(layoutkind.sequential)]
    protected class keyboardhookstruct
    {
      public int vkcode;
      public int scancode;
      public int flags;
      public int time;
      public int dwextrainfo;
    }
    [dllimport("user32.dll", charset = charset.auto,
      callingconvention = callingconvention.stdcall, setlasterror = true)]
    protected static extern int setwindowshookex(
      int idhook,
      hookproc lpfn,
      intptr hmod,
      int dwthreadid);
    [dllimport("user32.dll", charset = charset.auto,
      callingconvention = callingconvention.stdcall, setlasterror = true)]
    protected static extern int unhookwindowshookex(int idhook);
    [dllimport("user32.dll", charset = charset.auto,
       callingconvention = callingconvention.stdcall)]
    protected static extern int callnexthookex(
      int idhook,
      int ncode,
      int wparam,
      intptr lparam);
    [dllimport("user32")]
    protected static extern int toascii(
      int uvirtkey,
      int uscancode,
      byte[] lpbkeystate,
      byte[] lpwtranskey,
      int fustate);
    [dllimport("user32")]
    protected static extern int getkeyboardstate(byte[] pbkeystate);
    [dllimport("user32.dll", charset = charset.auto, callingconvention = callingconvention.stdcall)]
    protected static extern short getkeystate(int vkey);
    protected delegate int hookproc(int ncode, int wparam, intptr lparam);
    protected const int wh_mouse_ll = 14;
    protected const int wh_keyboard_ll = 13;
    protected const int wh_mouse = 7;
    protected const int wh_keyboard = 2;
    protected const int wm_mousemove = 0x200;
    protected const int wm_lbuttondown = 0x201;
    protected const int wm_rbuttondown = 0x204;
    protected const int wm_mbuttondown = 0x207;
    protected const int wm_lbuttonup = 0x202;
    protected const int wm_rbuttonup = 0x205;
    protected const int wm_mbuttonup = 0x208;
    protected const int wm_lbuttondblclk = 0x203;
    protected const int wm_rbuttondblclk = 0x206;
    protected const int wm_mbuttondblclk = 0x209;
    protected const int wm_mousewheel = 0x020a;
    protected const int wm_keydown = 0x100;
    protected const int wm_keyup = 0x101;
    protected const int wm_syskeydown = 0x104;
    protected const int wm_syskeyup = 0x105;
    protected const byte vk_shift = 0x10;
    protected const byte vk_capital = 0x14;
    protected const byte vk_numlock = 0x90;
    protected const byte vk_lshift = 0xa0;
    protected const byte vk_rshift = 0xa1;
    protected const byte vk_lcontrol = 0xa2;
    protected const byte vk_rcontrol = 0x3;
    protected const byte vk_lalt = 0xa4;
    protected const byte vk_ralt = 0xa5;
    protected const byte llkhf_altdown = 0x20;
    #endregion
    #region private variables
    protected int _hooktype;
    protected int _handletohook;
    protected bool _isstarted;
    protected hookproc _hookcallback;
    #endregion
    #region properties
    public bool isstarted
    {
      get
      {
        return _isstarted;
      }
    }
    #endregion
    #region constructor
    public globalhook()
    {
      application.applicationexit += new eventhandler(application_applicationexit);
    }
    #endregion
    #region methods
    public void start()
    {
      if (!_isstarted &&
        _hooktype != 0)
      {
        // make sure we keep a reference to this delegate!
        // if not, gc randomly collects it, and a nullreference exception is thrown
        _hookcallback = new hookproc(hookcallbackprocedure);
        _handletohook = setwindowshookex(
          _hooktype,
          _hookcallback,
          //marshal.gethinstance(assembly.getexecutingassembly().getmodules()[0]),
          0);
          intptr.zero;
        // were we able to sucessfully start hook?
        if (_handletohook != 0)
        {
          _isstarted = true;
        }
      }
    }
    public void stop()
    {
      if (_isstarted)
      {
        unhookwindowshookex(_handletohook);
        _isstarted = false;
      }
    }
    protected virtual int hookcallbackprocedure(int ncode, int32 wparam, intptr lparam)
    {
      // this method must be overriden by each extending hook
      return 0;
    }
    protected void application_applicationexit(object sender, eventargs e)
    {
      if (_isstarted)
      {
        stop();
      }
    }
    #endregion
  }
}

using system;
using system.text;
using system.windows.forms;
using system.runtime.interopservices;
namespace mousekeyboardlibrary
{
  /// <summary>
  /// captures global keyboard events
  /// </summary>
  public class keyboardhook : globalhook
  {
    #region events
    public event keyeventhandler keydown;
    public event keyeventhandler keyup;
    public event keypresseventhandler keypress;
    #endregion
    #region constructor
    public keyboardhook()
    {
      _hooktype = wh_keyboard_ll;
    }
    #endregion
    #region methods
    protected override int hookcallbackprocedure(int ncode, int wparam, intptr lparam)
    {
      bool handled = false;
      if (ncode > -1 && (keydown != null || keyup != null || keypress != null))
      {
        keyboardhookstruct keyboardhookstruct =
          (keyboardhookstruct)marshal.ptrtostructure(lparam, typeof(keyboardhookstruct));
        // is control being held down?
        bool control = ((getkeystate(vk_lcontrol) & 0x80) != 0) ||
                ((getkeystate(vk_rcontrol) & 0x80) != 0);
        // is shift being held down?
        bool shift = ((getkeystate(vk_lshift) & 0x80) != 0) ||
               ((getkeystate(vk_rshift) & 0x80) != 0);
        // is alt being held down?
        bool alt = ((getkeystate(vk_lalt) & 0x80) != 0) ||
              ((getkeystate(vk_ralt) & 0x80) != 0);
        // is capslock on?
        bool capslock = (getkeystate(vk_capital) != 0);
        // create event using keycode and control/shift/alt values found above
        keyeventargs e = new keyeventargs(
          (keys)(
            keyboardhookstruct.vkcode |
            (control ? (int)keys.control : 0) |
            (shift ? (int)keys.shift : 0) |
            (alt ? (int)keys.alt : 0)
            ));
        // handle keydown and keyup events
        switch (wparam)
        {
          case wm_keydown:
          case wm_syskeydown:
            if (keydown != null)
            {
              keydown(this, e);
              handled = handled || e.handled;
            }
            break;
          case wm_keyup:
          case wm_syskeyup:
            if (keyup != null)
            {
              keyup(this, e);
              handled = handled || e.handled;
            }
            break;
        }
        // handle keypress event
        if (wparam == wm_keydown &&
          !handled &&
          !e.suppresskeypress &&
          keypress != null)
        {
          byte[] keystate = new byte[256];
          byte[] inbuffer = new byte[2];
          getkeyboardstate(keystate);
          if (toascii(keyboardhookstruct.vkcode,
               keyboardhookstruct.scancode,
               keystate,
               inbuffer,
               keyboardhookstruct.flags) == 1)
          {
            char key = (char)inbuffer[0];
            if ((capslock ^ shift) && char.isletter(key))
              key = char.toupper(key);
            keypresseventargs e2 = new keypresseventargs(key);
            keypress(this, e2);
            handled = handled || e.handled;
          }
        }
      }
      if (handled)
      {
        return 1;
      }
      else
      {
        return callnexthookex(_handletohook, ncode, wparam, lparam);
      }
    }
    #endregion
  }
}

using system;
using system.text;
using system.runtime.interopservices;
using system.windows.forms;
namespace mousekeyboardlibrary
{
  /// <summary>
  /// standard keyboard shortcuts used by most applications
  /// </summary>
  public enum standardshortcut
  {
    copy,
    cut,
    paste,
    selectall,
    save,
    open,
    new,
    close,
    print
  }
  /// <summary>
  /// simulate keyboard key presses
  /// </summary>
  public static class keyboardsimulator
  {
    #region windows api code
    const int keyeventf_extendedkey = 0x1;
    const int keyeventf_keyup = 0x2;
    [dllimport("user32.dll")]
    static extern void keybd_event(byte key, byte scan, int flags, int extrainfo);
    #endregion
    #region methods
    public static void keydown(keys key)
    {
      keybd_event(parsekey(key), 0, 0, 0);
    }
    public static void keyup(keys key)
    {
      keybd_event(parsekey(key), 0, keyeventf_keyup, 0);
    }
    public static void keypress(keys key)
    {
      keydown(key);
      keyup(key);
    }
    public static void simulatestandardshortcut(standardshortcut shortcut)
    {
      switch (shortcut)
      {
        case standardshortcut.copy:
          keydown(keys.control);
          keypress(keys.c);
          keyup(keys.control);
          break;
        case standardshortcut.cut:
          keydown(keys.control);
          keypress(keys.x);
          keyup(keys.control);
          break;
        case standardshortcut.paste:
          keydown(keys.control);
          keypress(keys.v);
          keyup(keys.control);
          break;
        case standardshortcut.selectall:
          keydown(keys.control);
          keypress(keys.a);
          keyup(keys.control);
          break;
        case standardshortcut.save:
          keydown(keys.control);
          keypress(keys.s);
          keyup(keys.control);
          break;
        case standardshortcut.open:
          keydown(keys.control);
          keypress(keys.o);
          keyup(keys.control);
          break;
        case standardshortcut.new:
          keydown(keys.control);
          keypress(keys.n);
          keyup(keys.control);
          break;
        case standardshortcut.close:
          keydown(keys.alt);
          keypress(keys.f4);
          keyup(keys.alt);
          break;
        case standardshortcut.print:
          keydown(keys.control);
          keypress(keys.p);
          keyup(keys.control);
          break;
      }
    }
    static byte parsekey(keys key)
    {
      // alt, shift, and control need to be changed for api function to work with them
      switch (key)
      {
        case keys.alt:
          return (byte)18;
        case keys.control:
          return (byte)17;
        case keys.shift:
          return (byte)16;
        default:
          return (byte)key;
      }
    }
    #endregion
  }
}

using system;
using system.text;
using system.windows.forms;
using system.runtime.interopservices;
namespace mousekeyboardlibrary
{
  /// <summary>
  /// captures global mouse events
  /// </summary>
  public class mousehook : globalhook
  {
    #region mouseeventtype enum
    private enum mouseeventtype
    {
      none,
      mousedown,
      mouseup,
      doubleclick,
      mousewheel,
      mousemove
    }
    #endregion
    #region events
    public event mouseeventhandler mousedown;
    public event mouseeventhandler mouseup;
    public event mouseeventhandler mousemove;
    public event mouseeventhandler mousewheel;
    public event eventhandler click;
    public event eventhandler doubleclick;
    #endregion
    #region constructor
    public mousehook()
    {
      _hooktype = wh_mouse_ll;
    }
    #endregion
    #region methods
    protected override int hookcallbackprocedure(int ncode, int wparam, intptr lparam)
    {
      if (ncode > -1 && (mousedown != null || mouseup != null || mousemove != null))
      {
        mousellhookstruct mousehookstruct =
          (mousellhookstruct)marshal.ptrtostructure(lparam, typeof(mousellhookstruct));
        mousebuttons button = getbutton(wparam);
        mouseeventtype eventtype = geteventtype(wparam);
        mouseeventargs e = new mouseeventargs(
          button,
          (eventtype == mouseeventtype.doubleclick ? 2 : 1),
          mousehookstruct.pt.x,
          mousehookstruct.pt.y,
          (eventtype == mouseeventtype.mousewheel ? (short)((mousehookstruct.mousedata >> 16) & 0xffff) : 0));
        // prevent multiple right click events (this probably happens for popup menus)
        if (button == mousebuttons.right && mousehookstruct.flags != 0)
        {
          eventtype = mouseeventtype.none;
        }
        switch (eventtype)
        {
          case mouseeventtype.mousedown:
            if (mousedown != null)
            {
              mousedown(this, e);
            }
            break;
          case mouseeventtype.mouseup:
            if (click != null)
            {
              click(this, new eventargs());
            }
            if (mouseup != null)
            {
              mouseup(this, e);
            }
            break;
          case mouseeventtype.doubleclick:
            if (doubleclick != null)
            {
              doubleclick(this, new eventargs());
            }
            break;
          case mouseeventtype.mousewheel:
            if (mousewheel != null)
            {
              mousewheel(this, e);
            }
            break;
          case mouseeventtype.mousemove:
            if (mousemove != null)
            {
              mousemove(this, e);
            }
            break;
          default:
            break;
        }
      }
      return callnexthookex(_handletohook, ncode, wparam, lparam);
    }
    private mousebuttons getbutton(int32 wparam)
    {
      switch (wparam)
      {
        case wm_lbuttondown:
        case wm_lbuttonup:
        case wm_lbuttondblclk:
          return mousebuttons.left;
        case wm_rbuttondown:
        case wm_rbuttonup:
        case wm_rbuttondblclk:
          return mousebuttons.right;
        case wm_mbuttondown:
        case wm_mbuttonup:
        case wm_mbuttondblclk:
          return mousebuttons.middle;
        default:
          return mousebuttons.none;
      }
    }
    private mouseeventtype geteventtype(int32 wparam)
    {
      switch (wparam)
      {
        case wm_lbuttondown:
        case wm_rbuttondown:
        case wm_mbuttondown:
          return mouseeventtype.mousedown;
        case wm_lbuttonup:
        case wm_rbuttonup:
        case wm_mbuttonup:
          return mouseeventtype.mouseup;
        case wm_lbuttondblclk:
        case wm_rbuttondblclk:
        case wm_mbuttondblclk:
          return mouseeventtype.doubleclick;
        case wm_mousewheel:
          return mouseeventtype.mousewheel;
        case wm_mousemove:
          return mouseeventtype.mousemove;
        default:
          return mouseeventtype.none;
      }
    }
    #endregion
  }
}

using system;
using system.text;
using system.runtime.interopservices;
using system.drawing;
using system.windows.forms;
namespace mousekeyboardlibrary
{
  /// <summary>
  /// and x, y point on the screen
  /// </summary>
  public struct mousepoint
  {
    public mousepoint(point p)
    {
      x = p.x;
      y = p.y;
    }
    public int x;
    public int y;
    public static implicit operator point(mousepoint p)
    {
      return new point(p.x, p.y);
    }
  }
  /// <summary>
  /// mouse buttons that can be pressed
  /// </summary>
  public enum mousebutton
  {
    left = 0x2,
    right = 0x8,
    middle = 0x20
  }
  /// <summary>
  /// operations that simulate mouse events
  /// </summary>
  public static class mousesimulator
  {
    #region windows api code
    [dllimport("user32.dll")]
    static extern int showcursor(bool show);
    [dllimport("user32.dll")]
    static extern void mouse_event(int flags, int dx, int dy, int buttons, int extrainfo);
    const int mouseeventf_move = 0x1;
    const int mouseeventf_leftdown = 0x2;
    const int mouseeventf_leftup = 0x4;
    const int mouseeventf_rightdown = 0x8;
    const int mouseeventf_rightup = 0x10;
    const int mouseeventf_middledown = 0x20;
    const int mouseeventf_middleup = 0x40;
    const int mouseeventf_wheel = 0x800;
    const int mouseeventf_absolute = 0x8000;
    #endregion
    #region properties
    /// <summary>
    /// gets or sets a structure that represents both x and y mouse coordinates
    /// </summary>
    public static mousepoint position
    {
      get
      {
        return new mousepoint(cursor.position);
      }
      set
      {
        cursor.position = value;
      }
    }
    /// <summary>
    /// gets or sets only the mouse's x coordinate
    /// </summary>
    public static int x
    {
      get
      {
        return cursor.position.x;
      }
      set
      {
        cursor.position = new point(value, y);
      }
    }
    /// <summary>
    /// gets or sets only the mouse's y coordinate
    /// </summary>
    public static int y
    {
      get
      {
        return cursor.position.y;
      }
      set
      {
        cursor.position = new point(x, value);
      }
    }
    #endregion
    #region methods
    /// <summary>
    /// press a mouse button down
    /// </summary>
    /// <param name="button"></param>
    public static void mousedown(mousebutton button)
    {
      mouse_event(((int)button), 0, 0, 0, 0);
    }
    public static void mousedown(mousebuttons button)
    {
      switch (button)
      {
        case mousebuttons.left:
          mousedown(mousebutton.left);
          break;
        case mousebuttons.middle:
          mousedown(mousebutton.middle);
          break;
        case mousebuttons.right:
          mousedown(mousebutton.right);
          break;
      }
    }
    /// <summary>
    /// let a mouse button up
    /// </summary>
    /// <param name="button"></param>
    public static void mouseup(mousebutton button)
    {
      mouse_event(((int)button) * 2, 0, 0, 0, 0);
    }
    public static void mouseup(mousebuttons button)
    {
      switch (button)
      {
        case mousebuttons.left:
          mouseup(mousebutton.left);
          break;
        case mousebuttons.middle:
          mouseup(mousebutton.middle);
          break;
        case mousebuttons.right:
          mouseup(mousebutton.right);
          break;
      }
    }
    /// <summary>
    /// click a mouse button (down then up)
    /// </summary>
    /// <param name="button"></param>
    public static void click(mousebutton button)
    {
      mousedown(button);
      mouseup(button);
    }
    public static void click(mousebuttons button)
    {
      switch (button)
      {
        case mousebuttons.left:
          click(mousebutton.left);
          break;
        case mousebuttons.middle:
          click(mousebutton.middle);
          break;
        case mousebuttons.right:
          click(mousebutton.right);
          break;
      }
    }
    /// <summary>
    /// double click a mouse button (down then up twice)
    /// </summary>
    /// <param name="button"></param>
    public static void doubleclick(mousebutton button)
    {
      click(button);
      click(button);
    }
    public static void doubleclick(mousebuttons button)
    {
      switch (button)
      {
        case mousebuttons.left:
          doubleclick(mousebutton.left);
          break;
        case mousebuttons.middle:
          doubleclick(mousebutton.middle);
          break;
        case mousebuttons.right:
          doubleclick(mousebutton.right);
          break;
      }
    }
    /// <summary>
    /// show a hidden current on currently application
    /// </summary>
    public static void show()
    {
      showcursor(true);
    }
    /// <summary>
    /// hide mouse cursor only on current application's forms
    /// </summary>
    public static void hide()
    {
      showcursor(false);
    }
    #endregion
  }
}

using system;
using system.collections.generic;
using system.componentmodel;
using system.data;
using system.drawing;
using system.linq;
using system.text;
using system.windows.forms;
using mousekeyboardlibrary;
namespace sampleapplication
{
  /*
   上面的5个类编译成dll引用,使用例子
   */
  public partial class hooktestform : form
  {
    mousehook mousehook = new mousehook();
    keyboardhook keyboardhook = new keyboardhook();
    public hooktestform()
    {
      initializecomponent();
    }
    private void testform_load(object sender, eventargs e)
    {
      mousehook.mousemove += new mouseeventhandler(mousehook_mousemove);
      mousehook.mousedown += new mouseeventhandler(mousehook_mousedown);
      mousehook.mouseup += new mouseeventhandler(mousehook_mouseup);
      mousehook.mousewheel += new mouseeventhandler(mousehook_mousewheel);
      keyboardhook.keydown += new keyeventhandler(keyboardhook_keydown);
      keyboardhook.keyup += new keyeventhandler(keyboardhook_keyup);
      keyboardhook.keypress += new keypresseventhandler(keyboardhook_keypress);
      mousehook.start();
      keyboardhook.start();
      setxylabel(mousesimulator.x, mousesimulator.y);
    }
    void keyboardhook_keypress(object sender, keypresseventargs e)
    {
      addkeyboardevent(
        "keypress",
        "",
        e.keychar.tostring(),
        "",
        "",
        ""
        );
    }
    void keyboardhook_keyup(object sender, keyeventargs e)
    {
      addkeyboardevent(
        "keyup",
        e.keycode.tostring(),
        "",
        e.shift.tostring(),
        e.alt.tostring(),
        e.control.tostring()
        );
    }
    void keyboardhook_keydown(object sender, keyeventargs e)
    {
      addkeyboardevent(
        "keydown",
        e.keycode.tostring(),
        "",
        e.shift.tostring(),
        e.alt.tostring(),
        e.control.tostring()
        );
    }
    void mousehook_mousewheel(object sender, mouseeventargs e)
    {
      addmouseevent(
        "mousewheel",
        "",
        "",
        "",
        e.delta.tostring()
        );
    }
    void mousehook_mouseup(object sender, mouseeventargs e)
    {
      addmouseevent(
        "mouseup",
        e.button.tostring(),
        e.x.tostring(),
        e.y.tostring(),
        ""
        );
    }
    void mousehook_mousedown(object sender, mouseeventargs e)
    {
      addmouseevent(
        "mousedown",
        e.button.tostring(),
        e.x.tostring(),
        e.y.tostring(),
        ""
        );
    }
    void mousehook_mousemove(object sender, mouseeventargs e)
    {
      setxylabel(e.x, e.y);
    }
    void setxylabel(int x, int y)
    {
      curxylabel.text = string.format("current mouse point: x={0}, y={1}", x, y);
    }
    void addmouseevent(string eventtype, string button, string x, string y, string delta)
    {
      listview1.items.insert(0,
        new listviewitem(
          new string[]{
            eventtype,
            button,
            x,
            y,
            delta
          }));
    }
    void addkeyboardevent(string eventtype, string keycode, string keychar, string shift, string alt, string control)
    {
      listview2.items.insert(0,
         new listviewitem(
           new string[]{
            eventtype,
            keycode,
            keychar,
            shift,
            alt,
            control
        }));
    }
    private void testform_formclosed(object sender, formclosedeventargs e)
    {
      // not necessary anymore, will stop when application exits
      //mousehook.stop();
      //keyboardhook.stop();
    }
  }
}

更多关于c#相关内容感兴趣的读者可查看本站专题:《c#常见控件用法教程》、《winform控件用法总结》、《c#数据结构与算法教程》、《c#面向对象程序设计入门教程》及《c#程序设计之线程使用技巧总结

希望本文所述对大家c#程序设计有所帮助。