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. 《Linux内核分析》chapter4

  2. 原型设计(“留拍”Axure整体操作过程)

    使用 Axure 来设计原型[通过 视频(自己录视频上传到优酷网站) 来介绍 “留拍” 的基本 原型 ,后续再 美化界面 和 补充 详细功能]: 请点击下图的播放按钮来弹出视频(通过URL连接):

  3. atcoder A - Frog 1(DP)

    A - Frog 1 Time Limit: 2 sec / Memory Limit: 1024 MB Score : 100100 points Problem Statement There a ...

  4. NSLog debug时打印 release时不打印

    创建.h文件,添加以下代码 #ifdef  DEBUG #define NSLog(...)  NSLog(__VA_ARGS__) #else #define NSLog(...)  {} #end ...

  5. Comparer Under Centos 7

    Kompare 效果还行.

  6. Git—学习笔记1

    Git是一种分布式版本控制工具,现阶段比较流行的版本控制工具主要分为:集中式版本控制工具盒分布式版本控制工具. 集中式版本控制工具:SVN和CVS为代表 集中式版本控制系统(每次都得从SVN服务器数据 ...

  7. back to top 回到顶部按钮 css+js

    效果 html <p id="back-to-top"><a href="#top"><span></span> ...

  8. String()与toString的区别

    1..toString()可以将所有的的数据都转换为字符串,但是要排除null 和 undefined 代码示例: var a = null.toString()--报错 var b = underf ...

  9. (一) 关于配置travis-ci持续集成python pytest测试的相关记录

    首先由于公司用上了高大上的travis-ci商用版,一直想试着学学弄弄看.现在要写openapi的相关测试,而且要在travis-ci上集成.我就想体验一下这个过程.所以自己弄了一个public的仓库 ...

  10. Tomcat7/8访问Server Status、Manager App、Host Manager出现403 forbidden

    在配置好Tomcat7/8后,我们往往需要访问Tomcat7/8的Manager以及Host Manager.就需要在tomcat-users.xml中配置用户角色来实现.在地址栏输入:localho ...