博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用c#捕获usb扫描枪扫描二维码、条形码结果(支持中文版)
阅读量:4163 次
发布时间:2019-05-26

本文共 5203 字,大约阅读时间需要 17 分钟。

之前在18年写过一个,当时我是没有遇到需要使用中文的情况,因为二维码都是我自己控制生成的,如果遇到中文,我会提前进行编码编程unicode编码,所以,没有专门针对中文符号做支持

但一年多以来,不少人询问,或者在博客下留言,提出了中文扫码支持的需要,于是老顾就从新把程序从故纸堆里翻了出来,毕竟很久没弄这个了,还得自己重新读一遍代码,真晕。。。。。

好在,中文支持已经实现了

public class ScanerCodes        {            private int ts = 500; // 指定输入间隔为500毫秒以内时为连续输入            private List
> _keys = new List
>(); private List
_keydown = new List
(); // 保存组合键状态 private List
_result = new List
(); // 返回结果集 private List
_alt = new List
(); // 保存alt按下时的各键位 private DateTime _last = DateTime.Now; private byte[] _state = new byte[256]; private string _key = string.Empty; private string _cur = string.Empty; public EventMsg Event { get { if (_keys.Count == 0) { return new EventMsg(); } else { return _keys[_keys.Count - 1][_keys[_keys.Count - 1].Count - 1]; } } } public List
KeyDowns { get { return _keydown; } } public DateTime LastInput { get { return _last; } } public byte[] KeyboardState { get { return _state; } } public int KeyDownCount { get { return _keydown.Count; } } public string Result { get { if (_result.Count > 0) { return _result[_result.Count - 1].Trim(); } else { return null; } } } public string CurrentKey { get { return _key; } } public string CurrentChar { get { return _cur; } } public bool isShift { get { return _keydown.Contains(160) || _keydown.Contains(161); } } public bool isAlt { get { return _keydown.Contains(164) || _keydown.Contains(165); } } public bool isControl { get { return _keydown.Contains(162) || _keydown.Contains(163); } } public void Clear() { _keys.Clear(); _result.Clear(); } public void Add(EventMsg msg) { #region 记录按键信息 // 首次按下按键 if (_keys.Count == 0) { _keys.Add(new List
()); _keys[0].Add(msg); _result.Add(string.Empty); } // 未释放其他按键时按下按键 else if (_keydown.Count > 0) { _keys[_keys.Count - 1].Add(msg); } // 单位时间内按下按键 else if (((TimeSpan)(DateTime.Now - _last)).TotalMilliseconds < ts) { _keys[_keys.Count - 1].Add(msg); } // 从新记录输入内容 else { _keys.Add(new List
()); _keys[_keys.Count - 1].Add(msg); _result.Add(string.Empty); } if (_keys.Count > 10) { _keys.RemoveAt(0); } #endregion _last = DateTime.Now; #region 获取键盘状态 // 记录正在按下的按键 if (msg.paramH < 128 && !_keydown.Contains(msg.message)) { _keydown.Add(msg.message); } // 清除已松开的按键 if (msg.paramH > 127 && _keydown.Contains(msg.message)) { _keydown.Remove(msg.message); } #endregion #region 计算按键信息 int v = msg.message & 0xff; int c = msg.paramL & 0xff; StringBuilder strKeyName = new StringBuilder(500); if (GetKeyNameText(c * 65536, strKeyName, 255) > 0) { _key = strKeyName.ToString().Trim(new char[] { ' ', '\0' }); GetKeyboardState(_state); if (_key.Length == 1 && msg.paramH < 128) { // 根据键盘状态和shift缓存判断输出字符 _cur = ShiftChar(_key, isShift, _state).ToString(); _result[_result.Count - 1] += _cur; } else if (msg.paramH < 128 && isAlt) { _alt.Add(_key); } else if (msg.paramH > 127 && (msg.message == 164 || msg.message == 165)) { string composite = string.Empty; for (int i = 0; i < _alt.Count; i++) { composite += _alt[i]; } composite = Regex.Replace(composite, @"[^0-9]+", ""); string hex = Convert.ToInt32(composite).ToString("x"); if (hex.Length % 2 == 1) { hex = "0" + hex; } string str = Regex.Replace(hex, @"([0-9a-f]{2})", "%$1"); _cur = System.Web.HttpUtility.UrlDecode(str, Encoding.GetEncoding(936)); _result[_result.Count - 1] += _cur; _alt.Clear(); } else { _cur = string.Empty; } } #endregion } private char ShiftChar(string k, bool isShiftDown, byte[] state) { bool capslock = state[0x14] == 1; bool numlock = state[0x90] == 1; bool scrolllock = state[0x91] == 1; bool shiftdown = state[0xa0] == 1; char chr = (capslock ? k.ToUpper() : k.ToLower()).ToCharArray()[0]; if (isShiftDown) { if (chr >= 'a' && chr <= 'z') { chr = (char)((int)chr - 32); } else if (chr >= 'A' && chr <= 'Z') { chr = (char)((int)chr + 32); } else { string s = "`1234567890-=[];',./"; string u = "~!@#$%^&*()_+{}:\"<>?"; if (s.IndexOf(chr) >= 0) { return (u.ToCharArray())[s.IndexOf(chr)]; } } } return chr; } }

说起来,其实也没有修改很多东西,只对ScanerCodes这个类做了下微调,其他代码我就不再复制过来了,请参考原文

以下是中文支持的思路和尝试过程

首先,根据原文中不吃辣的阿银同学提出的问题,左右shift键paramH值不同的问题专门测试了一下,发现的确存在这种问题

那么第一步就是调整isShift,这里有个测试结果,有兴趣继续魔改的可以看一下

paramH,message0,160	// Lshift down128,160 // Lshift up1,161	// Rshift down129,161 // Rshift up0,162   // Lctrl down128,162 // Lctrl up1,163	// Rctrl down129,163	// Rctrl up32,164	// Lalt down128,164	// Lalt up33,165	// Ralt down129,165 // Ralt up

我这里使用的还是科密扫描枪,如果其他型号扫描枪有不同的结果,请自行尝试

isShift修改为判断已按下的键中,是否存在左右shift键对应的编号

然后,尝试进行中文扫码,直接一脸懵逼了。。。。所有的_key得到的结果都是长度大于1的内容,这都什么和什么啊,然后发现捕捉到了32,164的组合,这不是按alt键了吗?一脸疑惑中。。。。

然后通过调试发现,之后的键盘信息_key给我的是 Numpad 4,Numpad 5,Numpad 7,Numpad 9,Numpad 4。。。。。。

一脸惊讶!我是知道按住alt不送,直接在数字小键盘上输入数字可以出现任意符号的,难道扫描枪扫到中文也是这么搞得?

直接用数字小键盘尝试了下Alt+45794。。。。出现了一个“测”字,好吧。。。。这个是我生成的二维码。。。。。

那么有了这个结果,后边就相对简单了,直接加一个状态,isAlt,嗯,顺便支持左右Alt

然后重新定义一个数组_alt,用来记录alt键释放前的所有键盘信息

最后,在alt键释放的时候将_alt数组中的信息组合起来,得到小键盘数字顺序,并清空_alt数组,以便下一次继续获取中文符号

好了,得到了数字后就需要把数字转成中文了,然后当我使用(char)45794转出来的内容是个韩文字符的时候,我差点崩溃了。。。NND,扫描枪居然有字符集设置,而不是使用的unicode!

行吧,如果有人购买的扫描枪在数字转字符时不对,那一定是编码的锅,自己测试到底是什么编码吧!

于是,我就将数字转成16进制,然后补%,冒充urldecode的结果,然后使用gb2312进行urldecode,得到了正确结果,中文支持完成

 

转载地址:http://pxvxi.baihongyu.com/

你可能感兴趣的文章
matplotlib画图基础篇(一)
查看>>
python爬虫基础---pyquery解析
查看>>
python爬虫---scrapy入门(一个实例来了解一下scrapy爬虫流程)
查看>>
Debug与Release版本的区别
查看>>
VS2008 Unicode和多字节编码区别
查看>>
SHELLEXECUTEINFO 和 ShellExecuteEx的使用
查看>>
在VC中调用WebService
查看>>
VC++调用webservice (不使用.NET的托管技术)
查看>>
VS2008非托管c++访问webservice服务
查看>>
C++extern用法
查看>>
vc++生成程序不需要.net运行环境的可以执行exe程序的方法
查看>>
fstream默认不支持中文路径和输出整数带逗号的解决办法
查看>>
各种程序打包软件的安装命令
查看>>
Wise Installation使用中注意的问题
查看>>
WinCE开发环境的搭建
查看>>
让fstream支持中文路径
查看>>
Wise Installation使用中注意问题 总结
查看>>
wince 禁止程序标题栏上的退出按钮X
查看>>
线程池原理及创建(C++实现)
查看>>
世界上能做一个链接器的人坐不满一屋!做个编译器和链接器应该看的书籍
查看>>