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 ...
随机推荐
- SSIM (Structural SIMilarity) 结构相似性
公式基于样本x和 y 之间的三个比较衡量:亮度 (luminance).对比度 (contrast) 和结构 (structure). 每次计算的时候都从图片上取一个 N*N的窗口,然后不断滑动窗口进 ...
- 5-1 嵌套while循环应用
package com.imooc; public class forDemo { public static void main(String[] args) { ;//外重循环的循环变量: ;// ...
- 使用JSQLParser解析SQL中涉及到的表
首先添加Maven依赖: <dependency> <groupId>com.github.jsqlparser</groupId> <artifactId& ...
- [Google] 9717 取数对弈
我写的Python代码: class Solution(object): def getNumberGame(self, n, nums): m = len(nums) dp = [[0] * m f ...
- STM32驱动模数转换芯片ADS1120(PT100铂电阻测温度)第2篇
1. 先看下原理图,原理图是电流从IDAC1流出,提供驱动,然后R(REF)这个电阻上的电压作为参考,读取AIN0和AIN1的电压,那么可以测量出来电阻值. 2. 上图是官方给出的参考,下图是我实际用 ...
- web端自动化——selenium项目集成HTML测试报告
参考内容: 虫师:<selenium2自动化测试实战——基于python语言> PS:书中的代码,只能做参考,最好还是自己码一码,不一定照搬就全是对的,实践出真知... 随着软件不断迭代功 ...
- robot:截图关键字
参考: https://www.cnblogs.com/hong-fithing/p/9656221.html--python https://blog.csdn.net/weixin_4315628 ...
- 高级UI-沉浸式设计
关于沉浸式设计,在国内指的是Toolbar和系统状态栏相统一,而谷歌官方给出的沉浸式则是指整个界面为UI所用,而这里所说的沉浸式则是指的前者,涉及4.4和5.0及以上,4.4以下的Android做不出 ...
- IDEA遇到项目包后面出现% classes,% lines covered该怎么解决
IDEA遇到项目包后面出现% classes,% lines covered该怎么解决 这个问题嘛,我一个同学已经问我第二遍了.这次又是他问的,所以我就写一下教程吧 出现这种问题的原因:就是你点运行 ...
- 【Luogu P3919】可持久化数组
数组是一种单点修改,单点查询的基础数据结构. 如果要对数组改进,使之可持久化,那么显然我们需要利用其它的数据结构来改进它. 对于单点修改和单点查询两种操作,很容易发现可持久化线段树也是支持这种操作的. ...