求教:C#监听扫码枪,解析二维码

玄之 2021-01-23 07:11:21
C#写的程序,监听扫码枪扫二维码,时而能行,时而不行。。
求来一位大神给解决一下。。。在线等,挺急的
积分只有这么多了。。

钩子类,用于安装和卸载钩子

/// <summary>
/// 开始监听
/// </summary>
/// <returns></returns>
public bool Start()
{
_qrCode.Clear();
if (_hookProc == null || _hookHandle == IntPtr.Zero)
_hookProc = KeyboardHookProc;
//获取指针
IntPtr inpp = Kernel32Library.GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
//添加Hook
_hookHandle = User32Library.SetWindowsHookEx((int)HookType.WH_KEYBOARD_LL, _hookProc, inpp, 0);
Runing = true;
return true;
}

/// <summary>
/// 停止监听
/// </summary>
/// <returns></returns>
public bool Stop()
{
bool unhookSuccess = false;
if (_hookHandle != null || _hookHandle != IntPtr.Zero)
{
unhookSuccess = User32Library.UnhookWindowsHookEx(_hookHandle);
_hookHandle = IntPtr.Zero;
Runing = false;
}
return unhookSuccess;
}

/// <summary>
/// 钩子回调函数
/// </summary>
/// <param name="nCode"></param>
/// <param name="wParam"></param>
/// <param name="lParam"></param>
/// <returns></returns>
private int KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode == 0)
{
KeyboardMessage msg = (KeyboardMessage)Marshal.PtrToStructure(lParam, typeof(KeyboardMessage));
_qrCode.Add(msg);
LogUtility.Info("Msg解析值:" + msg.vkCode + " 二维码扫码结果:" + _qrCode.Result);
//vkCode=13表示回车
if (msg.vkCode == 13 && msg.paramH == 0 && !string.IsNullOrEmpty(_qrCode.Result))
{
QRCodeProcess(_qrCode.Result);
}
}
return User32Library.CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam);
}


解析键盘输入

/// <summary>
/// 增加键盘信息
/// </summary>
/// <param name="msg"></param>
public void Add(KeyboardMessage msg)
{
#region 记录按键信息
// 首次按下按键
if (_keys.Count == 0)
{
_keys = new List<KeyboardMessage>();
_keys.Add(msg);
_result = string.Empty;
}
// 未释放其他按键时按下按键
else if (_keydown.Count > 0)
{

_keys.Add(msg);
}
// 单位时间内按下按键
else if (((TimeSpan)(DateTime.Now - _last)).TotalMilliseconds < Interval)
{
_keys.Add(msg);
}
// 从新记录输入内容
else
{
_keys = new List<KeyboardMessage>();
_keys.Add(msg);
_result = string.Empty;
}
#endregion

_last = DateTime.Now;

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

#region 计算按键信息
int v = msg.vkCode & 0xff;
int c = msg.paramL & 0xff;
StringBuilder strKeyName = new StringBuilder(500);
if (User32Library.GetKeyNameText(c * 65536, strKeyName, 255) > 0)
{
_currentKey = strKeyName.ToString().Trim(new char[] { ' ', '\0' });
User32Library.GetKeyboardState(_state);
if (_currentKey.Length == 1 && msg.paramH == 0)
{
// 根据键盘状态和shift缓存判断输出字符
_cur = ShiftChar(_currentKey, isShift, _state).ToString();
_result += _cur;
}
}
#endregion
}

/// <summary>
///
/// </summary>
/// <param name="k"></param>
/// <param name="isShiftDown"></param>
/// <param name="state"></param>
/// <returns></returns>
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')
{
if (chr == 'Z')
{
string s = "";
}
chr = (char)((int)chr + 32);
}
else
{
string s = "`1234567890-=[];',./";
string u = "~!@#$%^&*()_+{}:\"<>?";
if (s.IndexOf(chr) >= 0)
{
return (u.ToCharArray())[s.IndexOf(chr)];
}
}
}
return chr;
}
...全文
2690 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
wmycom 2021-03-17
  • 打赏
  • 举报
回复
我做过很多很多这样的程序,就如大家所说,换串口枪,监听serialport获取数据事件就好了,然后你说的解析二维码。。。如果你的设备是可以扫描二维码的,人家本身扫码枪已经硬解回来给你了。除非你是拍照识别类的设备,用ZXING吧
dugupiaoyun 2021-03-15
  • 打赏
  • 举报
回复
你说时而能行时而不行,那么估计也就2个地方了,一个是你的Start方法 public bool Start() { _qrCode.Clear(); if (_hookProc == null || _hookHandle == IntPtr.Zero) _hookProc = KeyboardHookProc; //获取指针 IntPtr inpp = Kernel32Library.GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName); //添加Hook _hookHandle = User32Library.SetWindowsHookEx((int)HookType.WH_KEYBOARD_LL, _hookProc, inpp, 0); Runing = true; return true; } 你确定_hookHandle不等于0吗就直接返回true. 再一个因为你是USB扫码枪,实际上它是模拟键盘输入的。那么问题有可能在钩子回调方法那里, return User32Library.CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam); 这句是继续下一个钩子,如果返回1或者就没执行到这就出错了,那么也可能就会出现时而能行,时而不行的情况,所以检查下你定义的QRCodeProcess事件里,是否有报错。
zov 2021-03-15
  • 打赏
  • 举报
回复
怀疑你这个代码在造飞机
Carlven2012 2021-03-13
  • 打赏
  • 举报
回复
我的扫码枪是普通的条码扫码枪,下面是我获取扫码的代码:

private int iStep = 0;
        private int n;
        public string strRet = "";
        protected override void WndProc(ref Message m)//监视Windows消息
        {
            const int WM_KEYDOWN = 0x100;
            const int WM_KEYUP = 0x101;
            const int WM_CHAR = 0x0102;

            switch (m.Msg)
            {
                case WM_KEYDOWN:    
                    {
                        //begin --------------------------------------
                        iStep = 1;
                    }
                    break;
                case WM_CHAR:
                    {
                        if(iStep==1){
                            iStep = 2;
                            n = m.WParam.ToInt32();
                            System.Diagnostics.Debug.Write(n+" / "+Convert.ToChar(n)+"\n");
                            strRet = strRet + Convert.ToChar(n).ToString(); 
                        }
                        else { iStep = 0; }
                    }break;
                case WM_KEYUP:
                    {
                        if (iStep == 2)
                        {
                            iStep = 3;
                            if (m.WParam.ToInt32() == 13)
                            {
                                this.lb.Text = "当前条码为:" + strRet;
                                this.listBox1.Items.Add(strRet);
                                iStep = 0;
                                strRet = "";
                            }
                        }
                        else { iStep = 0; }
                    }break;
            }
            base.WndProc(ref m);
        }
glb21 2021-03-13
  • 打赏
  • 举报
回复
很多usb扫码枪有两种模式,默认是键盘输入模式,也可以配置成usb装串口模式。
沉默的隐者 2021-03-08
  • 打赏
  • 举报
回复
提问了如果解决了把解决结果发下呗
阿麦 2021-01-28
  • 打赏
  • 举报
回复
扫码枪的驱动应该会有提供回调处理接口的吧
正怒月神 2021-01-28
  • 打赏
  • 举报
回复
另外,感觉你的写法,可能有点问题, 比如释放钩子等等的,我好像没看到。
正怒月神 2021-01-28
  • 打赏
  • 举报
回复
没什么太好的方法, 就是调试。 多年前也写过,和楼主类似的功能。 当时是把扫码枪扫描的数据,填充到第三方的一个网页上。 我总结下来,就是调试。。。。虽然调试一直触发虚拟按键很麻烦。
movsd 2021-01-27
  • 打赏
  • 举报
回复
引用 7 楼 巴士上的邂逅 的回复:
换成串口扫码枪吧
weixin_48567397 2021-01-27
  • 打赏
  • 举报
回复
好像 IPAA上面有答案
weixin_48567397 2021-01-27
  • 打赏
  • 举报
回复
这个我觉得很容易
这不是鸭头 2021-01-27
  • 打赏
  • 举报
回复
不是那种串口输出的扫码枪吗?
郑剑1996 2021-01-26
  • 打赏
  • 举报
回复
扫码枪不是相当于键盘吗?
兔子-顾问 2021-01-26
  • 打赏
  • 举报
回复
如果是收银机上,可以在需要扫码时候使某个特定的文本框获得焦点等待输入。
Mr Dang 2021-01-25
  • 打赏
  • 举报
回复
应该是QRCodeProcess(_qrCode.Result)在回调函数里面占用时间太长了,导致User32Library.CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam)得不到及时执行,你屏蔽掉QRCodeProcess只打印先试下,确认是不是这个问题。是的话就容易了 ,开个线程后台去执行QRCodeProcess就完事了。
ziqi0716 2021-01-25
  • 打赏
  • 举报
回复
请用正确地打开方式来写代码 写个设备应用软件,钩子都给用上了还?拍脑袋拍的吧?好好看看人家的sdk之类的说明吧.
玄之 2021-01-24
  • 打赏
  • 举报
回复
引用 3 楼 以专业开发人员为伍 的回复:
人家设备“正常地”操作键盘,你弄个钩子干什么? 正常地处理键盘事件编程就可以了。
是不获取焦点情况下需要监听扫码枪。。扫码枪获取的东西不进行任何显示,焦点是在其他程序上。
巴士上的邂逅 2021-01-24
  • 打赏
  • 举报
回复
换成串口扫码枪吧
  • 打赏
  • 举报
回复
扫描枪纯粹是躺枪了。你应该测试你的钩子是否破坏了系统。就好像一个小偷它给电网里边搭入了自己的电缆了,他现在关心人家电网大扰动,关心人家不给他稳定送电,关心人家把钩子给自动断掉了,而更应该先去关心自己这个行为是否合法。
加载更多回复(4)

110,561

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧