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

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

程序员文章站 2022-07-01 17:02:49
本文实例讲述了c#使用钩子获得按键信息的方法。分享给大家供大家参考。具体如下: 窗体相关代码: using system; using system.coll...

本文实例讲述了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#程序设计有所帮助。