zoukankan      html  css  js  c++  java
  • 红外条码扫描器的另类使用C#版

    3年前写了一篇《USB口的红外条形码扫描器的另类使用》,不过相关代码是VB编写,在这几年之间,有许多网友提出需要C#版的,起初还以为由VB修改C#应该很容易,最近研究了一下,发现C#和VB调用API的机制还是有所不同的,在迁移的过程中还是会遇到不少问题,所以我专门抽时间做了一个基于C#的程序。

          【目前的条形码扫描器有点类似外接键盘(其实从消息传送上它就相当于一个键盘),把输入焦点定位到可输入的控件上,一扫描相应的条形码信息就输入到文本框中去了,但是如果没有输入焦点,或另一个不相干的程序获得输入焦点,那就有点乱套了。我想实现的是,不管什么情况,只要扫描器一工作,我的程序就能自动激活,并能获得当前输入的条形码信息。 实现思路:我用的是litele牌的USB口的红外条形码扫描器,仔细分析了一下,扫描成功后,以键盘按键消息的形式把条形码输入信息通知给系统。这样通过键盘钩子就可以方便的获得该信息了。但是,怎样区分信息是键盘还是条形码输入的哪?很简单,条形码扫描器在很短的时间内输入了至少3个字符以上信息,并且以“回车”作为结束字符,在这种思想指引下,很完美的实现了预定功能。】

         VB相关的代码请见:http://blog.csdn.net/yefanqiu/archive/2006/08/30/1144881.aspx

        

         

     

     


     

    窗体相关代码:

    using System;  
    using System.Collections.Generic;  
    using System.ComponentModel;  
    using System.Data;  
    using System.Drawing;  
    using System.Text;  
    using System.Windows.Forms;  
      
    namespace ReadBadCode  
    {  
        public partial class frmTest : Form  
        {  
            BarCodeHook BarCode = new BarCodeHook();  
            public frmTest()  
            {  
                InitializeComponent();  
                BarCode.BarCodeEvent += new BarCodeHook.BarCodeDelegate(BarCode_BarCodeEvent);  
            }  
      
            private delegate void ShowInfoDelegate(BarCodeHook.BarCodes barCode);  
            private void ShowInfo(BarCodeHook.BarCodes barCode)  
            {  
                if (this.InvokeRequired)  
                {  
                    this.BeginInvoke(new ShowInfoDelegate(ShowInfo), new object[] { barCode });  
                }  
                else  
                {  
                    textBox1.Text = barCode.KeyName;  
                    textBox2.Text = barCode.VirtKey.ToString();  
                    textBox3.Text = barCode.ScanCode.ToString();  
                    textBox4.Text = barCode.AscII.ToString();  
                    textBox5.Text = barCode.Chr.ToString();  
                    textBox6.Text = barCode.IsValid ? barCode.BarCode : "";  
                }  
            }  
      
            void BarCode_BarCodeEvent(BarCodeHook.BarCodes barCode)  
            {  
                ShowInfo(barCode);  
            }  
      
            private void frmTest_Load(object sender, EventArgs e)  
            {  
                BarCode.Start();  
            }  
      
            private void frmTest_FormClosed(object sender, FormClosedEventArgs e)  
            {  
                BarCode.Stop();  
            }  
      
            private void textBox6_TextChanged(object sender, EventArgs e)  
            {  
                if (textBox6.Text.Length > 0)  
                {  
                    MessageBox.Show(textBox6.Text);  
                }  
            }  
        }  
    }

    BarCodeHook 类:

    using System;  
    using System.Collections.Generic;  
    using System.Text;  
    using System.Runtime.InteropServices;  
    using System.Reflection;  
      
    namespace ReadBadCode  
    {  
        public class BarCodeHook  
        {  
            public delegate void BarCodeDelegate(BarCodes barCode);  
            public event BarCodeDelegate BarCodeEvent;  
      
            public struct BarCodes  
            {  
                public int VirtKey;      //虚拟码  
                public int ScanCode;     //扫描码  
                public string KeyName;   //键名  
                public uint AscII;       //AscII  
                public char Chr;         //字符  
      
                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);  
      
            [DllImport("user32", EntryPoint = "GetKeyNameText")]  
            private static extern int GetKeyNameText(int lParam, StringBuilder lpBuffer, int nSize);  
      
            [DllImport("user32", EntryPoint = "GetKeyboardState")]  
            private static extern int GetKeyboardState(byte[] pbKeyState);  
      
            [DllImport("user32", EntryPoint = "ToAscii")]  
            private static extern bool ToAscii(int VirtualKey, int ScanCode, byte[] lpKeyState, ref uint lpChar, int uFlags);  
      
            delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);  
            BarCodes barCode = new BarCodes();  
            int hKeyboardHook = 0;  
            string strBarCode = "";  
      
            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;  //扫描码  
      
                        StringBuilder strKeyName = new StringBuilder(255);  
                        if (GetKeyNameText(barCode.ScanCode * 65536, strKeyName, 255) > 0)  
                        {  
                            barCode.KeyName = strKeyName.ToString().Trim(new char[] { ' ', '/0' });  
                        }  
                        else  
                        {  
                            barCode.KeyName = "";  
                        }  
      
                        byte[] kbArray = new byte[256];  
                        uint uKey = 0;  
                        GetKeyboardState(kbArray);                                          
                        if (ToAscii(barCode.VirtKey, barCode.ScanCode, kbArray, ref uKey, 0))  
                        {  
                            barCode.AscII = uKey;  
                            barCode.Chr = Convert.ToChar(uKey);  
                        }  
      
                        if (DateTime.Now.Subtract(barCode.Time).TotalMilliseconds > 50)   
                        {  
                            strBarCode = barCode.Chr.ToString();  
                        }  
                        else  
                        {  
                            if ((msg.message & 0xff) == 13 && strBarCode.Length > 3)   //回车  
                            {  
                                barCode.BarCode = strBarCode;  
                                barCode.IsValid = true;  
                            }  
                            strBarCode += barCode.Chr.ToString();  
                        }  
      
                        barCode.Time = DateTime.Now;  
                        if (BarCodeEvent != null) BarCodeEvent(barCode);    //触发事件  
                        barCode.IsValid = false;  
                    }  
                }  
                return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);            
            }  
              
            // 安装钩子   
            public bool Start()  
            {  
                if (hKeyboardHook == 0)  
                {  
                    //WH_KEYBOARD_LL = 13  
                    hKeyboardHook = SetWindowsHookEx(13, new HookProc(KeyboardHookProc), Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);  
                }  
                return (hKeyboardHook != 0);  
            }  
      
            // 卸载钩子   
            public bool Stop()  
            {  
                if (hKeyboardHook != 0)  
                {  
                    return UnhookWindowsHookEx(hKeyboardHook);  
                }  
                return true;  
            }  
        }  
    }  

    【注意】和VB程序不同,要想测试实际的效果,必须执行编译后的Exe文件,在开发环境直接运行会没有效果的。



    C# Winform中无焦点状态下获取键盘输入或者USB扫描枪数据


    类文件:
      1 using System;
      2 using System.Collections.Generic;
      3 using System.Text;
      4 using System.Runtime.InteropServices;
      5 using System.Reflection;
      6 
      7 namespace Common
      8 {
      9     public class BardCodeHooK
     10     {
     11         public delegate void BardCodeDeletegate(BarCodes barCode);
     12         public event BardCodeDeletegate BarCodeEvent;
     13 
     14         public struct BarCodes
     15         {
     16             public int VirtKey;//虚拟吗
     17             public int ScanCode;//扫描码
     18             public string KeyName;//键名
     19             public uint Ascll;//Ascll
     20             public char Chr;//字符
     21 
     22             public string BarCode;//条码信息
     23             public bool IsValid;//条码是否有效
     24             public DateTime Time;//扫描时间
     25         }
     26 
     27         private struct EventMsg
     28         {
     29             public int message;
     30             public int paramL;
     31             public int paramH;
     32             public int Time;
     33             public int hwnd;
     34         }
     35 
     36         [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
     37         private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
     38 
     39         [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
     40         private static extern bool UnhookWindowsHookEx(int idHook);
     41 
     42         [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
     43         private static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);
     44 
     45         [DllImport("user32", EntryPoint = "GetKeyNameText")]
     46         private static extern int GetKeyNameText(int IParam, StringBuilder lpBuffer, int nSize);
     47 
     48         [DllImport("user32", EntryPoint = "GetKeyboardState")]
     49         private static extern int GetKeyboardState(byte[] pbKeyState);
     50 
     51         [DllImport("user32", EntryPoint = "ToAscii")]
     52         private static extern bool ToAscii(int VirtualKey, int ScanCode, byte[] lpKeySate, ref uint lpChar, int uFlags);
     53 
     54         delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
     55         BarCodes barCode = new BarCodes();
     56         int hKeyboardHook = 0;
     57         string strBarCode = "";
     58 
     59         private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
     60         {
     61             if (nCode == 0)
     62             {
     63                 EventMsg msg = (EventMsg)Marshal.PtrToStructure(lParam, typeof(EventMsg));
     64                 if (wParam == 0x100)//WM_KEYDOWN=0x100
     65                 {
     66                     barCode.VirtKey = msg.message & 0xff;//虚拟吗
     67                     barCode.ScanCode = msg.paramL & 0xff;//扫描码
     68                     StringBuilder strKeyName = new StringBuilder(225);
     69                     if (GetKeyNameText(barCode.ScanCode * 65536, strKeyName, 255) > 0)
     70                     {
     71                         barCode.KeyName = strKeyName.ToString().Trim(new char[] { ' ', '' });
     72                     }
     73                     else
     74                     {
     75                         barCode.KeyName = "";
     76                     }
     77                     byte[] kbArray = new byte[256];
     78                     uint uKey = 0;
     79                     GetKeyboardState(kbArray);
     80 
     81 
     82                     if (ToAscii(barCode.VirtKey, barCode.ScanCode, kbArray, ref uKey, 0))
     83                     {
     84                         barCode.Ascll = uKey;
     85                         barCode.Chr = Convert.ToChar(uKey);
     86                     }
     87 
     88                     TimeSpan ts = DateTime.Now.Subtract(barCode.Time);
     89 
     90                     if (ts.TotalMilliseconds > 50)
     91                     {
     92                         strBarCode = barCode.Chr.ToString();
     93                     }
     94                     else
     95                     {
     96                         if ((msg.message & 0xff) == 13 && strBarCode.Length > 3)
     97                         {
     98                             barCode.BarCode = strBarCode;
     99                             barCode.IsValid = true;
    100                         }
    101                         strBarCode += barCode.Chr.ToString();
    102                     }
    103                     barCode.Time = DateTime.Now;
    104                     if (BarCodeEvent != null) BarCodeEvent(barCode);//触发事件
    105                     barCode.IsValid = false;
    106                 }
    107             }
    108             return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
    109         }
    110 
    111         //安装钩子
    112         public bool Start()
    113         {
    114             if (hKeyboardHook == 0)
    115             {
    116                 //WH_KEYBOARD_LL=13
    117                 hKeyboardHook = SetWindowsHookEx(13, new HookProc(KeyboardHookProc), Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);
    118             }
    119             return (hKeyboardHook != 0);
    120         }
    121 
    122         //卸载钩子
    123         public bool Stop()
    124         {
    125             if (hKeyboardHook != 0)
    126             {
    127                 return UnhookWindowsHookEx(hKeyboardHook);
    128             }
    129             return true;
    130         }
    131     }
    132 }


    页面中用法:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    namespace Common
    {
        public partial class FrmMain : Form
        {
            BardCodeHooK BarCode = new BardCodeHooK();
            public FrmMain()
            {
                InitializeComponent();
                BarCode.BarCodeEvent += new BardCodeHooK.BardCodeDeletegate(BarCode_BarCodeEvent);
            }
            private delegate void ShowInfoDelegate(BardCodeHooK.BarCodes barCode);
            private void ShowInfo(BardCodeHooK.BarCodes barCode)
            {
                if (this.InvokeRequired)
                {
                    this.BeginInvoke(new ShowInfoDelegate(ShowInfo), new object[] { barCode });
                }
                else
                {
                    textBox1.Text = barCode.KeyName;
                    textBox2.Text = barCode.VirtKey.ToString();
                    textBox3.Text = barCode.ScanCode.ToString();
                    textBox4.Text = barCode.Ascll.ToString();
                    textBox5.Text = barCode.Chr.ToString();
                    textBox6.Text = barCode.IsValid? barCode.BarCode : "";//是否为扫描枪输入,如果为true则是 否则为键盘输入
                    textBox7.Text += barCode.KeyName;
                    //MessageBox.Show(barCode.IsValid.ToString());
                }
            }
            //C#中判断扫描枪输入与键盘输入
            //Private DateTime _dt = DateTime.Now;  //定义一个成员函数用于保存每次的时间点
            //private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
            //{
            //    DateTime tempDt = DateTime.Now;          //保存按键按下时刻的时间点
            //    TimeSpan ts = tempDt .Subtract(_dt);     //获取时间间隔
            //    if (ts.Milliseconds > 50)                           //判断时间间隔,如果时间间隔大于50毫秒,则将TextBox清空
            //        textBox1.Text = "";
            //    dt = tempDt ;
            //}
     
            void BarCode_BarCodeEvent(BardCodeHooK.BarCodes barCode)
            {
                ShowInfo(barCode);
            }
            private void FrmMain_Load(object sender, EventArgs e)
            {
                BarCode.Start();
            }
            private void FrmMain_FormClosed(object sender, FormClosedEventArgs e)
            {
                BarCode.Stop();
            }
            private void textBox6_TextChanged(object sender, EventArgs e)
            {
                if (textBox6.Text.Length > 0)
                {
                    MessageBox.Show("条码长度:" + textBox6.Text.Length + " 条码内容:" + textBox6.Text, "系统提示");
                }
            }
        }
    }

  • 相关阅读:
    HeadFirst设计模式之RMI介绍
    HeadFirst设计模式之状态模式
    算法Sedgewick第四版-第1章基础-001递归
    HeadFirst设计模式之组合模式
    HeadFirst设计模式之迭代器模式
    HeadFirst设计模式之模板方法模式
    HeadFirst设计模式之适配器模式
    CentOS-6.5-saltstack-安装
    Swift
    在OC中调用Swift类中定义delegate出现:Property 'delegate' not found on object of type ...
  • 原文地址:https://www.cnblogs.com/zhaoshujie/p/9594761.html
Copyright © 2011-2022 走看看