首页 > 编程语言 >使用c#捕获usb扫描枪扫描二维码、条形码结果(支持中文版)

使用c#捕获usb扫描枪扫描二维码、条形码结果(支持中文版)

时间:2023-05-23 14:13:19浏览次数:54  
标签:Count 扫描枪 return usb c# keydown keys msg string

前因

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

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

代码

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

        public class ScanerCodes
        {
            private int ts = 500; // 指定输入间隔为500毫秒以内时为连续输入
            private List<List<EventMsg>> _keys = new List<List<EventMsg>>();
            private List<int> _keydown = new List<int>();   // 保存组合键状态
            private List<string> _result = new List<string>();  // 返回结果集
            private List<string> _alt = new List<string>();     // 保存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<int> 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<EventMsg>());
                    _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<EventMsg>());
                    _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及其他
首先,根据原文中不吃辣的阿银同学提出的问题,左右shift键paramH值不同的问题专门测试了一下,发现的确存在这种问题

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

paramH,message
0,160    // Lshift down
128,160 // Lshift up
1,161    // Rshift down
129,161 // Rshift up
0,162   // Lctrl down
128,162 // Lctrl up
1,163    // Rctrl down
129,163    // Rctrl up
32,164    // Lalt down
128,164    // Lalt up
33,165    // Ralt down
129,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,得到了正确结果,中文支持完成

原文链接:https://blog.csdn.net/superwfei/article/details/101005215

标签:Count,扫描枪,return,usb,c#,keydown,keys,msg,string
From: https://www.cnblogs.com/alannxu/p/17425028.html

相关文章

  • Let’s Encrypted:一键申请SSL证书脚本
    wgethttps://raw.githubusercontent.com/nanqinlang-script/acme/master/acme_2.0.shbashacme_2.0.sh使用说明输入你的域名选择要生成证书的类型。输入数字0(生成RSA类型)或1(生成ECC类型)。若未选择则默认生成RSA类型用DNS方式验证域名所有权:添加脚本中显示的绿......
  • 直播app开发搭建,scroll-view封装自定义下拉刷新
    直播app开发搭建,scroll-view封装自定义下拉刷新完整代码 <!--container.vue--><template><view><scroll-viewscroll-y="true"class="scroll-view":refresher-enabled="refresh":refresher-triggered="triggered":refresher-t......
  • 1万多贺卡祝福节日祝福ACCESS\EXCEL数据库
    你是否在春节只能复制别人的祝福短信来发送?你是否在节日期间为给朋友送祝福无从下手?你是否在特殊日子和朋友打不开对话的开头?其实,很多情况下我们都需要一堆不同与别的人祝福语,用在节日上、用在交际上等日常备用。今天这一份数据就是祝福语大全,有节日、祝福两大类,子分类有50多个。......
  • CF1196F K-th Path 题解 floyd
    题目链接:https://codeforces.com/problemset/problem/1196/F题目大意:给定一个包含\(n\)个节点\(m\)条边的无向图(\(n,m\le2\cdot10^5\))。图中任意两点之间(如果连通的话)都存在一条最短路(节点\(i\)到它自己不算最短路,\(i\)到\(j\)的最短路和\(j\)到\(i\)的最短......
  • BootStrap导入excel
    BootStrap_实现导入Excel(BootStrap-InputFile)【实例】weixin_40877388于2020-03-3114:52:47发布5505收藏19分类专栏:BootStrap版权BootStrap专栏收录该内容2篇文章0订阅订阅专栏一、前言在批量加入学生信息的时候,我们通常采用Excel导入的方式,方便,快......
  • js导入excel&导出excel
    js导入excel&导出excel Excel导入html代码<buttonstyle={{color:'#1890ff',fontSize:'14px',cursor:'pointer'}}onClick={()=>{upFile();}}>导入</button><inputid="upFile"type="fil......
  • https部署与docker下nginx的转发+文件获取
    进入nginx容器查看是否有etc/nginx/cert目录将https的域名证书放到cert目录下配置80和443server{#listen80;#侦听80端口listen80;#侦听443端口,用于SSLserver_name127.zyfdtsite.com;client_max_body_size1024m;#charsetkoi8-r;#acc......
  • 工欲善其事必先利其器--CMake牛刀小试
    这里假设用户已经安装好MinGW编译套件!并配置好环境变量!具体怎么下载和配置网上教程非常多,这里贴上一个链接:不仅教你安装MinGW还教你安装VScode配置1、学习cplusplus编码为什么要学习CMake?在Windows下使用集成开发环境(IDE)开发项目时,一般会使用IDE自带的构建工具(如VisualStudio......
  • 8百多经典古诗学习鉴赏ACCESS\EXCEL数据库
    虽然古诗类的数据搞到过很多,但是有鉴赏、译文等鉴赏类字段的还是很少,而今天搞到一个古诗学习类数据库,虽然记录数不多,但大都有翻译、鉴赏、译文等字段内容,是小学生、中学生、高中生学习的好东西。朝代统计:金朝(2)、两汉(22)、明代(25)、南北朝(24)、清代(27)、宋代(348)、唐代(373)、魏晋(19)、五......
  • SignalR WebSocket通讯机制
    1、什么是SignalRASP.NETSignalR是一个面向ASP.NET开发人员的库,可简化向应用程序添加实时Web功能的过程。实时Web功能是让服务器代码在可用时立即将内容推送到连接的客户端,而不是让服务器等待客户端请求新数据。SignalR使用的三种底层传输技术分别是WebSocket......