五维思考

学习要加,骄傲要减,机会要乘,懒惰要除。 http://www.5dthink.cn

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

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[] { ' ', '\0' });
 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 + "\n条码内容:" + textBox6.Text, "系统提示");
            }
        }
    }
}

posted on 2015-03-11 12:54  五维思考  阅读(400)  评论(0编辑  收藏  举报

QQ群:1. 全栈码农【346906288】2. VBA/VSTO【2660245】