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

            }

        }

    }

}

红外条码扫描器的另类使用C#版的更多相关文章

  1. 超强工具集——GitHub 热点速览 Vol.47

    作者:HelloGitHub-小鱼干 本周 GitHub 趋势榜精彩至极,先是 JetBrains 开源的图像渲染引擎 Skia 有了 Java 封装,一开源便获得 500+ star,再是支持开发者 ...

  2. Revealjs网页版PPT让你复制粘贴另类装逼,简洁优雅又低调,不懂编程也看过来

    Revealjs网页版PPT让你复制粘贴另类装逼,简洁优雅又低调,不懂编程也看过来 要了解一个新知识我们可以从三个方面入手:是什么,有什么用,怎么用.下面我们就从这三个方面进行讲解Reveal.js噢 ...

  3. ETO的公开赛T1《矿脉开采》题解(另类版)

    这道题别看是签到题,写起来一点不简单 出题人的正解是双向搜索 我们把物品分成两半 每一半分别跑搜索 答案存下来,用个双指针合并即可 然后我构造了两组数据卡掉了他,不得不缩小数据范围 但我这里为什么要致 ...

  4. 智能手机+DIY红外=万能遥控器

    目前好像只有:三星S4.,努比亚大牛,华为荣耀3等几款新机才有红外遥控功能,那我们使用的手机没有这个功能怎么办?不要急我有办法呵呵,本次DIY材料好找又简单,大家都可以亲自试一试! DIY材料:红外二 ...

  5. 【Win 10 应用开发】RTM版的UAP项目解剖

    Windows 10 发布后,其实SDK也偷偷地在VS的自定义安装列表中出现了,今天开发人员中心也更新了下载.正式版的SDK在API结构上和以前预览的时候是一样的,只是版本变成10240罢了,所以大家 ...

  6. Android开发权威指南(第2版)新书发布

    <Android 开发权威指南(第二版)>是畅销书<Android开发权威指南>的升级版,内容更新超过80%,是一本全面介绍Android应用开发的专著,拥有45 章精彩内容供 ...

  7. TVB-Gone 红外编码方法

    每次都重新推算一遍,年纪大了还是记录一下吧(硬件版的TV-B-Gone的压缩编码跳过此段往下看) N900上有个TVB-Gone的程序,但是程序的红外编码往往都是对应的国外的电视,好多国产电视都不支持 ...

  8. 全球最受欢迎的十大Linux发行版(图)

    帮助新的Linux用户在越来越多的Linux发行版中选择最合适的操作系统,是创建这个网页的原因.它列出了迄今为止最流行的10个Linux发行版(另外增加的是FreeBSD,到目前为止最为流行的BSD系 ...

  9. Java面试宝典2013版(超长版)

    一. Java基础部分......................................................................................... ...

随机推荐

  1. Machine Learning Based Proactive Flow Entry Deletion for OpenFlow

    来源:IEEE 2018 作者:Hemin Yang and George F.Riley 摘要: 流表容量有限,因此高效管理流表至关重要.本文重点讨论了OpenFlow中定义的一种流表管理机制,即能 ...

  2. jQuery(六)

    $下常用方法 $().xxx:只能给jq对象用 $.xxx不仅可以给jq用也可以给原生js用,叫做工具方法 $.type() <script> $(function(){ var a= n ...

  3. HTML 选择器

    c56 div:nth-of-type(1) { margin-left: 12px; margin-top: 25px; } .c56 div:nth-of-type(2) { margin-top ...

  4. JavaScript浏览器历史的语法小问题

    https://www.w3schools.com/jsref/met_his_back.asp This is the same as clicking the "Back button& ...

  5. ASP.NET Web Service 标准SOAP开发案例代码(自定义验证安全头SOAPHeader)

    using System.Xml;using System.Xml.Serialization;using System.Web.Services.Protocols;using System.Con ...

  6. Test Scenarios for sending emails

    (test cases for composing or validating emails are not included)(make sure to use dummy email addres ...

  7. Linux(Debian) 上安装tomcat并注册服务开机自启动

    1.准备工作 a.下载tomcat linux的包,地址:http://tomcat.apache.org/download-80.cgi,我们下载的版本是8.0,下载方式如图:          b ...

  8. python之参数解包

    # 参数解包:将整个list当做参数传给函数 list = [1, 2, 4] def add_fn(a, b, c): return a + b + c sum = add_fn(*list) pr ...

  9. Flatpak 1.1.0发布:可终止运行Flatpak实例

    读 Flatpak的Alex Larsson发布了流行的Linux应用程序沙盒和分发框架的新版本,该框架有望成为跨Linux操作系统的应用程序分发的未来. Flatpak 1.1.0现已作为开始推出F ...

  10. mysql 启动和关闭外键约束

    在MySQL中删除一张表或一条数据的时候,出现 [Err] 1451 -Cannot delete or update a parent row: a foreign key constraint f ...