收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
img
img

如果你需要这些资料,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

        {
            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);
            }
        }
        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);
            }
            #endregion
            _last = DateTime.Now;
            #region 获取键盘状态
            // 记录正在按下的按键
            if (msg.paramH == 0 && !_keydown.Contains(msg.message))
            {
                _keydown.Add(msg.message);
            }
            // 清除已松开的按键
            if (msg.paramH > 0 && _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 == 0)
                {
                    // 根据键盘状态和shift缓存判断输出字符
                    _cur = ShiftChar(_key, isShift, _state).ToString();
                    _result[_result.Count - 1] += _cur;
                }
                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;
        }
    }
    public struct EventMsg
    {
        public int message;
        public int paramL;
        public int paramH;
        public int Time;
        public int hwnd;
    }
}

}



### 分析需求的不同之处


基本原理与其他文章的没有什么不同,区别在于,扫描二维码时,结果不仅仅是数字,并且字母有大小写区分,还可能包含标点符号什么的



当然,我这个程序没有对8位ascii以上的字符集做支持,也就是不支持汉字什么的,需要对汉字支持的自己进行魔改好了


### 实现的过程解析


KeyboardHookProc 是用来捕捉键盘输入时间的,我的处理方式和网上其他文章的区别在于,每次捕捉到的内容都直接扔到数组中去,然后再触发事件返回给调用者,而扔给数组的方法就是Add方法了,这里的处理才是真正的核心


因为条形码中只有数字和部分符号,所以基本可以不用考虑键盘状态或组合键的情况,但二维码就不能不考虑了,尤其是有些验证信息还区分大小写的情况,例如二维码扫描结果是这样的内容“c=a0$nLD7\_49vSF9-1&n=1”,我使用的是科密ew-9200扫描枪,因为要区分扫描枪,所以对每个扫描枪追加的后缀设置,也就是&n=1部分,前面的才是扫描结果


那么通过事件监听,发现在键盘状态为小写时,a还是a,但是$是4,L是l,也就是说,我们无法通过键盘状态来获取我们的预期结果,但是我们发现了另一个现象,那就是相邻的几个EventMsg中paramH为0时,是表示按下了对应按钮,paramH大于零时表示松开了对应按钮,那么就有一个有意思的现象了,当出现字母a时,EventMsg中message相同的两次,一次paramH=0,一次paramH=128,而出现字母L时,相关的EventMsg为四个,分别是message=160 & paramH=0 , message=76 & paramH=0 , message=76 & paramH=128 , message=160 & paramH=129,于是就有了一个辅助记录是否组合键的变量及代码段




            #region 获取键盘状态
            // 记录正在按下的按键
            if (msg.paramH == 0 && !_keydown.Contains(msg.message))
            {
                _keydown.Add(msg.message);
            }
            // 清除已松开的按键
            if (msg.paramH > 0 && _keydown.Contains(msg.message))
            {
                _keydown.Remove(msg.message);
            }
            #endregion

可以根据\_keydown.Count来判断当前按下了几个键,可以使用\_keydown.Contains(160)判断是否按下了Shift键,然后使用ShiftChar方法来获取最终的按键对应字符  
  
 至于结果保存,我使用了一个数组List<List<EventMsg>>,对每次输入都单独进行记录,大家也可以自行修改以符合自己的习惯



最后,就是事件触发了




        if (ScanerEvent != null && msg.message == 13 && msg.paramH > 0 && !string.IsNullOrEmpty(codes.Result))
        {
            ScanerEvent(codes);
        }

当触发事件有定义,且当前按键时回车键松开,且已记录的字符串非空,则触发返回事件,其实这么看起来,感觉还是不算很难



好了,类说明大概就这样了,调用方法就更简单了




public partial class Scaner : Form

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
img
img

如果你需要这些资料,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

学提升的朋友。**
[外链图片转存中…(img-y9oqVC6b-1715635506646)]
[外链图片转存中…(img-9pCOMLNK-1715635506646)]

如果你需要这些资料,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

Logo

宁波官方开源宣传和活动阵地,欢迎各位和我们共建开源生态体系!

更多推荐