红外条码扫描器的另类使用C#版

时间:2023-03-10 07:06:02
红外条码扫描器的另类使用C#版

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

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

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

红外条码扫描器的另类使用C#版

红外条码扫描器的另类使用C#版


窗体相关代码:

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, "系统提示");

            }

        }

    }

}