请选择 进入手机版 | 继续访问电脑版

雨滴科技技术论坛

 找回密码
 立即注册
查看: 83|回复: 3

无焦点下获取条码枪的条码(Hook实现)

[复制链接]

3

主题

8

帖子

52

积分

注册会员

Rank: 2

积分
52
扫一扫,手机访问本帖
发表于 2019-9-24 21:07:15 | 显示全部楼层 |阅读模式
   USB扫码枪为即插即用,通过类似键盘的方式和系统进行交互,扫描出来的数据在默认的条件下是通过焦点直接显示。要想把USB扫码枪的数据整合到上位机,有两种方式:
(一):安装官方提供的虚拟驱动,模拟串口接收。这种方法的缺点是驱动只支持win7的,用不了。操作麻烦。
(二):使用键盘钩子,勾取扫描枪虚拟按键,进行键盘虚拟码和ASCII码的转换后获取数据。
在程序开发中要实现系统钩子其实很简单,调用Win32的API即可。
代码其实很简单:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;


namespace Volume
{
    public class BarCodeHook
    {
        public delegate void BarCodeDelegate(BarCodes barCode);
        public event BarCodeDelegate BarCodeEvent;


        public struct BarCodes
        {
            public int VirtKey;      //虚拟码  
            public int ScanCode;     //扫描码  


            public string BarCode;   //条码信息  
            public bool IsValid;     //条码是否有效  
            public DateTime Time;    //扫描时间  
        }


        private struct EventMsg
        {
            public int message;
            public int paramL;
            public int paramH;
            public int Time;
            public int hwnd;
        }


        [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);


        delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);


        BarCodes barCode = new BarCodes();
        int hKeyboardHook = 0;
        List _barcode = new List(100);
        private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
        {
            if (nCode == 0)
            {
                EventMsg msg = (EventMsg)Marshal.PtrToStructure(lParam, typeof(EventMsg));


                if (wParam == 0x100)   //WM_KEYDOWN = 0x100  
                {
                    barCode.VirtKey = msg.message & 0xff;  //虚拟码  
                    barCode.ScanCode = msg.paramL & 0xff;  //扫描码  




                    if (DateTime.Now.Subtract(barCode.Time).TotalMilliseconds > 100)
                    {
                        _barcode.Clear();
                    }
                    else
                    {
                        if ((msg.message & 0xff) == 13 && _barcode.Count > 5)   //回车  
                        {
                            barCode.BarCode = new String(_barcode.ToArray());


                            barCode.IsValid = true;
                            _barcode.Clear();
                        }
                    }


                    barCode.Time = DateTime.Now;
                    if (BarCodeEvent != null) BarCodeEvent(barCode);    //触发事件  
                    barCode.IsValid = false;
                    _barcode.Add(Convert.ToChar(msg.message & 0xff));
                }
            }
            return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
        }


        private HookProc hookproc;
        // 安装钩子   
        public bool Start()
        {
            if (hKeyboardHook == 0)
            {
                hookproc = new HookProc(KeyboardHookProc);
                //WH_KEYBOARD_LL = 13  
                hKeyboardHook = SetWindowsHookEx(13, hookproc, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);
            }
            return (hKeyboardHook != 0);
        }


        // 卸载钩子   
        public bool Stop()
        {
            if (hKeyboardHook != 0)
            {
                return UnhookWindowsHookEx(hKeyboardHook);
            }
            return true;
        }


    }
}
程序当判断短时间内连续输入大于5个,并且回车结束则判断为条码。
然后在界面代码使用如下:
      public BarCodeHook BarCode = new BarCodeHook();
        public Form1()
        {
            InitializeComponent();
            BarCode.Start();
            BarCode.BarCodeEvent += new BarCodeHook.BarCodeDelegate(BarCode_BarCodeEvent);
        }
        private void BarCode_BarCodeEvent(BarCodeHook.BarCodes barCode)
        {
            if (barCode.IsValid)
            {
                this.BeginInvoke(new Action(() =>
                {                 
                    textBox1.Text = Regex.Replace(barCode.BarCode, @"\s", "");//使用正则过滤掉空格
                    bt_Install.Focus();
                }));
            }
        }


        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
           BarCode.Stop();
        }
结果图: 条码获取.png
使用起来还是很流畅的。




回复

使用道具 举报

375

主题

1512

帖子

5886

积分

论坛元老

Rank: 8Rank: 8

积分
5886
发表于 2019-9-25 16:25:20 | 显示全部楼层
键盘方式也是需要驱动,用的是系统标准驱动,把自己模拟成一个HID设备。
不用钩子的方式是,放焦点到一个输入框,条码枪相当于键盘输入。

钩子要注意释放,因为是系统全局的钩子。

能区分键盘来的还是条码枪来的呢?
回复 支持 反对

使用道具 举报

342

主题

1834

帖子

6654

积分

版主

Rank: 7Rank: 7Rank: 7

积分
6654
发表于 2019-9-25 17:52:18 | 显示全部楼层
回复

使用道具 举报

367

主题

1886

帖子

9204

积分

版主

Rank: 7Rank: 7Rank: 7

积分
9204
发表于 2019-10-7 11:43:51 | 显示全部楼层
C#中加载DLL的例子,我正需要这个例子
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

在线客服
在线咨询
咨询热线
0755-26787502-8006/8016
扫一扫二维码
直接访问本站

QQ|Archiver|手机版|小黑屋|雨滴科技  

GMT+8, 2019-10-18 18:51 , Processed in 0.088568 second(s), 30 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表