using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices; namespace **.Forms
{
/// <summary>
/// 获取键盘输入或者USB扫描枪数据 可以是没有焦点 应为使用的是全局钩子
/// USB扫描枪 是模拟键盘按下
/// 这里主要处理扫描枪的值,手动输入的值不太好处理
/// </summary>
public class BardCodeHook
{
public delegate void BardCodeDeletegate(BarCodes barCode);
public event BardCodeDeletegate BarCodeEvent; //定义成静态,这样不会抛出回收异常
private static HookProc hookproc; public struct BarCodes
{
public int VirtKey;//虚拟吗
public int ScanCode;//扫描码
public string KeyName;//键名
public uint Ascll;//Ascll
public char Chr;//字符 public string OriginalChrs; //原始 字符
public string OriginalAsciis;//原始 ASCII public string OriginalBarCode; //原始数据条码 public bool IsValid;//条码是否有效
public DateTime Time;//扫描时间, public string BarCode;//条码信息 保存最终的条码
} private struct EventMsg
{
public int message;
public int paramL;
public int paramH;
public int Time;
public int hwnd;
} #region DllImport [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 IParam, StringBuilder lpBuffer, int nSize); [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[] lpKeySate, ref uint lpChar, int uFlags); [DllImport("kernel32.dll")]
public static extern IntPtr GetModuleHandle(string name);
#endregion delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
BarCodes barCode = new BarCodes();
int hKeyboardHook = ;
StringBuilder sbBarCode = new StringBuilder(); private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
{
int i_calledNext = -;
if (nCode == )
{
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();
if (GetKeyNameText(barCode.ScanCode * , strKeyName, ) > )
{
barCode.KeyName = strKeyName.ToString().Trim(new char[] { ' ', '\0' });
}
else
{
barCode.KeyName = "";
}
byte[] kbArray = new byte[];
uint uKey = ;
GetKeyboardState(kbArray); if (ToAscii(barCode.VirtKey, barCode.ScanCode, kbArray, ref uKey, ))
{
barCode.Ascll = uKey;
barCode.Chr = Convert.ToChar(uKey); barCode.OriginalChrs += " " + Convert.ToString(barCode.Chr);
barCode.OriginalAsciis += " " + Convert.ToString(barCode.Ascll); barCode.OriginalBarCode += Convert.ToString(barCode.Chr); } TimeSpan ts = DateTime.Now.Subtract(barCode.Time); if (ts.TotalMilliseconds > )
{//时间戳,大于50 毫秒表示手动输入
sbBarCode.Remove(, sbBarCode.Length);
sbBarCode.Append(barCode.Chr.ToString()); barCode.OriginalChrs = " " + Convert.ToString(barCode.Chr);
barCode.OriginalAsciis = " " + Convert.ToString(barCode.Ascll); barCode.OriginalBarCode = Convert.ToString(barCode.Chr); }
else
{
if ((msg.message & 0xff) == && sbBarCode.Length > )
{//回车 barCode.BarCode = barCode.OriginalBarCode; barCode.IsValid = true;
sbBarCode.Remove(, sbBarCode.Length);
} sbBarCode.Append(barCode.Chr.ToString());
} try
{
if (BarCodeEvent != null && barCode.IsValid)
{ //barCode.BarCode = barCode.BarCode.Replace("\b", "").Replace("\0",""); 可以不需要 因为大于50毫秒已经处理
//先进行 WINDOWS事件往下传
i_calledNext = CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
GC.KeepAlive(hookproc); BarCodeEvent(barCode);//触发事件 barCode.BarCode = ""; barCode.OriginalChrs = "";
barCode.OriginalAsciis = "";
barCode.OriginalBarCode = "";
}
}
catch
{
}
finally
{
barCode.IsValid = false; //最后一定要 设置barCode无效
barCode.Time = DateTime.Now;
}
}
}
if (i_calledNext == -)
{
i_calledNext = CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
GC.KeepAlive(hookproc);
}
return i_calledNext;
} /// <summary>
/// 安装钩子
/// </summary>
/// <returns></returns>
public bool Start()
{
if (hKeyboardHook == )
{
hookproc = new HookProc(KeyboardHookProc); //GetModuleHandle 函数 替代 Marshal.GetHINSTANCE
//防止在 framework4.0中 注册钩子不成功
IntPtr modulePtr = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName); //WH_KEYBOARD_LL=13
//全局钩子 WH_KEYBOARD_LL
// hKeyboardHook = SetWindowsHookEx(13, hookproc, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0); hKeyboardHook = SetWindowsHookEx(, hookproc, modulePtr, ); //IntPtr intPtr = Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]);
//hKeyboardHook = SetWindowsHookEx(13, hookproc, intPtr, 0); GC.KeepAlive(hookproc);
}
return (hKeyboardHook != );
} /// <summary>
/// 卸载钩子
/// </summary>
/// <returns></returns>
public bool Stop()
{
if (hKeyboardHook != )
{
return UnhookWindowsHookEx(hKeyboardHook);
}
return true;
} }
}

使用方法:

private void Form_Load(object sender, EventArgs e)
{
bardCodeHook.Start();
bardCodeHook.BarCodeEvent += bardCodeHook_BarCodeEvent;
} private void Form_FormClosed(object sender, FormClosedEventArgs e)
{
bardCodeHook.Stop();
bardCodeHook.BarCodeEvent -= bardCodeHook_BarCodeEvent;
}

WinForm 无焦点获取键盘输入的更多相关文章

  1. 获取键盘输入或者USB扫描枪数据

    /// <summary> /// 获取键盘输入或者USB扫描枪数据 可以是没有焦点 应为使用的是全局钩子 /// USB扫描枪 是模拟键盘按下 /// 这里主要处理扫描枪的值,手动输入的 ...

  2. 在Delphi中使用键盘勾子获取键盘输入(译--5月7日)

    http://blog.sina.com.cn/s/blog_502b2e970100949s.html 获取键盘输入以控制无法接受输入焦点的控件考虑一些游戏,显示图片在TPainBox,但是TPai ...

  3. C# 无焦点获取扫码枪扫码信息

    代码网上有的是,多是需要窗体焦点直接show出扫码信息(usb,模拟键盘,hook) 怎样才能真的无焦点获取? 用串口方式 usb转串口 以接收串口通讯消息的方式获取扫码信息

  4. Go 获取键盘输入,进制转换

    #### Go 获取键盘输入,进制转换 最近爱上<<珂矣的心灵独语>> 连续听一下礼拜也不觉得厌: 喜欢她的宁静与安然,喜欢她的坦荡与欢喜,喜欢她的禅意与智慧; ***撑着一苇 ...

  5. java利用Scanner获取键盘输入

    首发地址:我的网易博客 在运行一个java程序的时候,可能我们需要在运行的时候传递一些参数进去...咋办呢... java提供了一个Scanner类,利用这个类,我们可以很方便的获取键盘输入的参数.. ...

  6. java 获取键盘输入常用的两种方法

    java 获取键盘输入常用的两种方法 方法1: 通过 Scanner Scanner input = new Scanner(System.in); String s = input.nextLine ...

  7. tkinter获取键盘输入

    tkinter获取键盘输入

  8. Java编程中获取键盘输入实现方法及注意事项

    Java编程中获取键盘输入实现方法及注意事项 1. 键盘输入一个数组 package com.wen201807.sort; import java.util.Scanner; public clas ...

  9. Java基础 - 获取键盘输入

    package com.demo3; import java.util.Scanner; /* * 使用 Scanner 获取键盘输入供程序使用 * * 使用步骤: * A:导包 * import j ...

随机推荐

  1. kotlin单个文件及文件夹复制例子

    最近学习kotlin,把java中的单个文件及包含文件夹的文件 复制操作改写为kotlin的代码,主要熟悉kotlin文件操作以及递归调用操作方法 演示代码如下: package com.exam.f ...

  2. django实战总结

    1.创建app命令 django-admin.py startapp app_name 2.数据库脚本命令 # 1. 创建更改的文件 python manage.py makemigrations # ...

  3. ISO/IEC 9899:2011 条款6.8.4——选择语句

    6.8.4 选择语句 语法 1.selection-statement: if    (    expression    )    statement if    (    expression   ...

  4. Python3入门(十三)——常用内置模块之集合模块collections

    1.namedtuple 主要用来定义一种数据类型:它具有Tuple的不变性,而且又能通过属性来访问 例如定义坐标: from collections import namedtuple Point ...

  5. 使用Maven完成SSM框架整合环境构建——基于Spring4和Mybatis3

    只言片语 使用Maven来搭建一个SSM环境,其实和使用手工倒入jar的过程没有多大区别,所用的jar包都是一样的,但是区别在与不用你手动导入jar包了,而是只修改pom.xml,maven会自动根据 ...

  6. Glide图片加载过程(简)

    iceIC 关注 2018.10.25 20:53* 字数 906 阅读 529评论 0喜欢 1 调研版本为4.7.1为了更加简单的理解,会将函数代码简化,详细代码请自行照源码对比 Glide用法 G ...

  7. PHPStudy后门事件分析

    PHP环境集成程序包phpStudy被公告疑似遭遇供应链攻击,程序包自带PHP的php_xmlrpc.dll模块隐藏有后门.经过分析除了有反向连接木马之外,还可以正向执行任意php代码. 影响版本 P ...

  8. 安装Windows和Ubuntu双系统

    发现关注消息 安装Windows和Ubuntu双系统     安装Windows和Ubuntu双系统 0.552016.12.10 15:54:41字数 2101阅读 6644 这几天开始动手做毕设啦 ...

  9. canal启动报错ERROR c.a.o.canal.parse.inbound.mysql.dbsync.DirectLogFetcher - I/O error while reading from client socket

  10. python 线程队列LifoQueue-LIFO(36)

    在 python线程队列Queue-FIFO  文章中已经介绍了 先进先出队列Queue,而今天给大家介绍的是第二种:线程队列LifoQueue-LIFO,数据先进后出类型,两者有什么区别呢? 一.队 ...