WinForm 无焦点获取键盘输入
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 无焦点获取键盘输入的更多相关文章
- 获取键盘输入或者USB扫描枪数据
/// <summary> /// 获取键盘输入或者USB扫描枪数据 可以是没有焦点 应为使用的是全局钩子 /// USB扫描枪 是模拟键盘按下 /// 这里主要处理扫描枪的值,手动输入的 ...
- 在Delphi中使用键盘勾子获取键盘输入(译--5月7日)
http://blog.sina.com.cn/s/blog_502b2e970100949s.html 获取键盘输入以控制无法接受输入焦点的控件考虑一些游戏,显示图片在TPainBox,但是TPai ...
- C# 无焦点获取扫码枪扫码信息
代码网上有的是,多是需要窗体焦点直接show出扫码信息(usb,模拟键盘,hook) 怎样才能真的无焦点获取? 用串口方式 usb转串口 以接收串口通讯消息的方式获取扫码信息
- Go 获取键盘输入,进制转换
#### Go 获取键盘输入,进制转换 最近爱上<<珂矣的心灵独语>> 连续听一下礼拜也不觉得厌: 喜欢她的宁静与安然,喜欢她的坦荡与欢喜,喜欢她的禅意与智慧; ***撑着一苇 ...
- java利用Scanner获取键盘输入
首发地址:我的网易博客 在运行一个java程序的时候,可能我们需要在运行的时候传递一些参数进去...咋办呢... java提供了一个Scanner类,利用这个类,我们可以很方便的获取键盘输入的参数.. ...
- java 获取键盘输入常用的两种方法
java 获取键盘输入常用的两种方法 方法1: 通过 Scanner Scanner input = new Scanner(System.in); String s = input.nextLine ...
- tkinter获取键盘输入
tkinter获取键盘输入
- Java编程中获取键盘输入实现方法及注意事项
Java编程中获取键盘输入实现方法及注意事项 1. 键盘输入一个数组 package com.wen201807.sort; import java.util.Scanner; public clas ...
- Java基础 - 获取键盘输入
package com.demo3; import java.util.Scanner; /* * 使用 Scanner 获取键盘输入供程序使用 * * 使用步骤: * A:导包 * import j ...
随机推荐
- laravel打印sql所执行的原生语句
DB::listen(function($sql) { foreach ($sql->bindings as $i => $binding) { if ($binding instance ...
- openresty开发系列12--lua介绍及常用数据类型简介
openresty开发系列12--lua介绍及常用数据类型简介 lua介绍 1993 年在巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de ...
- Spring 中使用了哪些设计模式?
好了,话不多说,开始今天的内容.spring中常用的设计模式达到九种,我们举例说明. 1.简单工厂模式 又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式 ...
- snmp oid 和厂商对应关系
<node oid="default" name="Unknown" type="workstation"/><node ...
- (一)IDEA修改HTML不生效(未热部署)
一.问题 IDEA 版本:2018.1.2 项目类型:SpringBoot 描述 : 修改JSP文件内容时,不会热部署,需要每次都重启项目才生效. 二.解决方案 加入Springboot开发者工具,即 ...
- 用VS Code写C#
目录 前言 下载SDK 安装C#支持 快速创建C#控制台 格式化代码 launch:launch.json must be configured. change 'program' to the pa ...
- iOS点击按钮第二次不能旋转View
原因: 用CGAffineTransformMakeRotation,每次旋转都要在之前最后的角度基础之上再转才有效果. - (void)clickAction: (UIButton *)button ...
- PngOptimizer PNG压缩工具
好用,非常好用,速度快. 把图片拖入即可,同文件夹备份替换压缩. 点击下载
- 正则表达式入门教程&&经典Javascript正则表达式
前言 例子: ^.+@.+\\..+$ 这样的代码曾经多次把我自己给吓退过.可能很多人也是被这样的代码给吓跑的吧.继续阅读本文将让你也可以自由应用这样的代码. 正文 教程:正则表达式30分钟入门教程 ...
- web端自动化——selenium3用法详解
selenium中文学习文档链接:https://selenium-python-zh.readthedocs.io/en/latest/getting-started.html selenium3+ ...