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. Hive跨集群迁移

    Hive跨集群迁移数据工作是会出现的事情, 其中涉及到数据迁移, metastore迁移, hive版本升级等. 1. 迁移hdfs数据至新集群hadoop distcp -skipcrccheck ...

  2. 【Python】使用POST方式抓取有道翻译结果

    1.安装requests库 2.打开有道翻译,按下F12,进入开发者模式,输入我爱青青,点击Network,再点击XHR 3.撰写爬虫 import requestsimport json # 使用有 ...

  3. hppts的理解

    参考: https://www.ruanyifeng.com/blog/2014/02/ssl_tls.html

  4. 函数返回new对象

    #include <iostream> using namespace std; // foo()函数本质上没什么问题,但建议你不要这样写代码 string &foo() { st ...

  5. jenkins离线安装插件

    2.jenkins离线安装插件 安装插件参照文档: https://blog.csdn.net/russ44/article/details/52266953 插件相关下载地址:http://upda ...

  6. 【docker 镜像源】解决quay.io和gcr.io国内无法访问的问题

    该问题容易导致image pull back off 错误,应当换源: 微软: https://yeasy.gitbooks.io/docker_practice/install/mirror.htm ...

  7. 组件文档系统-md-react-styleguidist

    推荐指数:

  8. docker 安装 tomcat8

    docker hub 查找 tomcat meiya@meiya:/etc/docker$ docker search tomcat NAME DESCRIPTION STARS OFFICIAL A ...

  9. PHP curl模拟ip和来源进行访问

    PHP curl模拟ip和来源进行访问<pre> public function moniurlqingqiu() { $ch = curl_init(); $curlurl = &quo ...

  10. pycharm 提示:this license **** has been cancelled(2)

    pycharm安装激活过程中,提示 this license **** has been cancelled .这个问题并不是你的激活码不对,而是需要修改系统的hosts文件,下面详细讲解下如何修改h ...