当前位置: 移动技术网 > IT编程>开发语言>c# > C#使用钩子获得按键信息的方法

C#使用钩子获得按键信息的方法

2019年07月18日  | 移动技术网IT编程  | 我要评论

本文实例讲述了c#使用钩子获得按键信息的方法。分享给大家供大家参考。具体如下:

窗体相关代码:

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 system.runtime.interopservices;
using system.threading;
using readbadcode;
namespace gouzi
{
 public partial class form2 : form
 {
  barcodehook barcode = new barcodehook();
  public form2()
  {
   initializecomponent();
   barcode.barcodeevent += new barcodehook.barcodedelegate(barcode_barcodeevent);
  }
  private delegate void showinfodelegate(barcodehook.barcodes barcode);
  private void showinfo(barcodehook.barcodes barcode)
  {
   if (this.invokerequired)
   {
    this.begininvoke(new showinfodelegate(showinfo), new object[] { barcode });
   }
   else
   {
    textbox1.text = barcode.keyname;//键名
    textbox2.text = barcode.virtkey.tostring();//虚拟码
    textbox3.text = barcode.scancode.tostring();//扫描码
    textbox4.text = barcode.ascii.tostring();//ascii
    textbox5.text = barcode.chr.tostring();//字符
    textbox6.text = barcode.isvalid ? barcode.barcode : "";
    //在这里进行键入值
   }
  }
  void barcode_barcodeevent(barcodehook.barcodes barcode)
  {
   showinfo(barcode);
  }
  private void form2_load(object sender, eventargs e)
  {
   barcode.start();
  }
  private void form2_stylechanged(object sender, eventargs e)
  {
   barcode.stop();
  }
 }
}

后台类代码:

using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.runtime.interopservices;
using system.reflection;
namespace readbadcode
{
 class barcodehook
 {
  public delegate void barcodedelegate(barcodes barcode);
  public event barcodedelegate barcodeevent;
  public struct barcodes
  {
   public int virtkey;  //虚拟码 
   public int scancode;  //扫描码 
   public string keyname; //键名 
   public uint ascii;  //ascii 
   public char chr;   //字符
   public string barcode; //条码信息 
   public bool isvalid;  //条码是否有效 
   public datetime time; //扫描时间 
  }
  private struct eventmsg
  {
   public int message;
   public int paraml;
   public int paramh;
   public int time;
   public int hwnd;
  }
  // 安装钩子 
  [dllimport("user32.dll", charset = charset.auto, callingconvention = callingconvention.stdcall)]
  private static extern int setwindowshookex(int idhook, hookproc lpfn, intptr hinstance, int threadid);
  // 卸载钩子
  [dllimport("user32.dll", charset = charset.auto, callingconvention = callingconvention.stdcall)]
  private static extern bool unhookwindowshookex(int idhook);
  // 继续下一个钩子
  [dllimport("user32.dll", charset = charset.auto, callingconvention = callingconvention.stdcall)]
  private static extern int callnexthookex(int idhook, int ncode, int32 wparam, intptr lparam);
  //获取键名的字符串
  [dllimport("user32", entrypoint = "getkeynametext")]
  private static extern int getkeynametext(int lparam, stringbuilder lpbuffer, int nsize);
  //将256个虚拟键复制到指定的缓冲区中
  [dllimport("user32", entrypoint = "getkeyboardstate")]
  private static extern int getkeyboardstate(byte[] pbkeystate);
  //将指定的虚拟键码和键盘状态为相应的字符串
  [dllimport("user32", entrypoint = "toascii")]
  private static extern bool toascii(int virtualkey, int scancode, byte[] lpkeystate, ref uint lpchar, int uflags);
  //声明定义回调函数
  delegate int hookproc(int ncode, int32 wparam, intptr lparam);
  barcodes barcode = new barcodes();
  int hkeyboardhook = 0;
  string strbarcode = "";
  private int keyboardhookproc(int ncode, int32 wparam, intptr lparam)
  {
   if (ncode == 0)
   {
    eventmsg msg = (eventmsg)marshal.ptrtostructure(lparam, typeof(eventmsg));
    if (wparam == 0x100) //wm_keydown = 0x100
    {
     barcode.virtkey = msg.message & 0xff; //虚拟码 
     barcode.scancode = msg.paraml & 0xff; //扫描码
     stringbuilder strkeyname = new stringbuilder(255);
     if (getkeynametext(barcode.scancode * 65536, strkeyname, 255) > 0)
     {
      barcode.keyname = strkeyname.tostring().trim(new char[] { ' ', '\0' });
     }
     else
     {
      barcode.keyname = "";
     }
     byte[] kbarray = new byte[256];
     uint ukey = 0;
     getkeyboardstate(kbarray);
     if (toascii(barcode.virtkey, barcode.scancode, kbarray, ref ukey, 0))
     {
      barcode.ascii = ukey;
      barcode.chr = convert.tochar(ukey);
     }
     if (datetime.now.subtract(barcode.time).totalmilliseconds > 50)
     {
      strbarcode = barcode.chr.tostring();
     }
     else
     {
      if ((msg.message & 0xff) == 13 && strbarcode.length > 3)
      //回车
      {
       barcode.barcode = strbarcode;
       barcode.isvalid = true;
      }
      strbarcode += barcode.chr.tostring();
     }
     barcode.time = datetime.now;
     if (barcodeevent != null) barcodeevent(barcode);
     //触发事件 
     barcode.isvalid = false;
    }
   }
   return callnexthookex(hkeyboardhook, ncode, wparam, lparam);
  }
  // 安装钩子 
  public bool start()
  {
   if (hkeyboardhook == 0)
   {
    //wh_keyboard_ll = 13 
    hkeyboardhook = setwindowshookex(13, new hookproc(keyboardhookproc), marshal.gethinstance(assembly.getexecutingassembly().getmodules()[0]), 0);
   }
   return (hkeyboardhook != 0);
  }
  // 卸载钩子 
  public bool stop()
  {
   if (hkeyboardhook != 0)
   {
    return unhookwindowshookex(hkeyboardhook);
   }
   return true;
  }
 }
}

【注意】要想测试实际的效果,必须执行编译后的exe文件,在开发环境直接运行会没有效果的。

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网