• 3535阅读
  • 0回复

[讨论]C# Winform 中无焦点状态下获取键盘输入或者 USB 扫描枪数据 [复制链接]

上一主题 下一主题
离线liangwei1362
 

只看楼主 倒序阅读 楼主  发表于: 2017-06-07

最近在做个国外很火的项目,碰到一些问题,下面的代码老是报错,哪位有经验的大神帮我看看~
扫描器是优力科的MS3398下面是扫描器的参数APIhttp://www.posunitech.com/products_detail/productId=83.html
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Runtime.InteropServices;
  5. using System.Text;
  6. namespace Common
  7. {
  8.    public class BardCodeHooK
  9.    {
  10.        public delegate void BardCodeDeletegate(BarCodes barCode);
  11.        public event BardCodeDeletegate BarCodeEvent;
  12.        public struct BarCodes
  13.        {
  14.            public int VirtKey;//虚拟吗
  15.            public int ScanCode;//扫描码
  16.            public string KeyName;//键名
  17.            public uint Ascll;//Ascll
  18.            public char Chr;//字符
  19.            public string BarCode;//条码信息
  20.            public bool IsValid;//条码是否有效
  21.            public DateTime Time;//扫描时间
  22.        }
  23.        private struct EventMsg
  24.        {
  25.            public int message;
  26.            public int paramL;
  27.            public int paramH;
  28.            public int Time;
  29.            public int hwnd;
  30.        }
  31.        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
  32.        private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
  33.        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
  34.        private static extern bool UnhookWindowsHookEx(int idHook);
  35.        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
  36.        private static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);
  37.        [DllImport("user32", EntryPoint = "GetKeyNameText")]
  38.        private static extern int GetKeyNameText(int IParam, StringBuilder lpBuffer, int nSize);
  39.        [DllImport("user32", EntryPoint = "GetKeyboardState")]
  40.        private static extern int GetKeyboardState(byte[] pbKeyState);
  41.        [DllImport("user32", EntryPoint = "ToAscii")]
  42.        private static extern bool ToAscii(int VirtualKey, int ScanCode, byte[] lpKeySate, ref uint lpChar, int uFlags);
  43.        delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
  44.        BarCodes barCode = new BarCodes();
  45.        int hKeyboardHook = 0;
  46.        string strBarCode = "";
  47.        private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
  48.        {
  49.            if (nCode == 0)
  50.            {
  51.                EventMsg msg = (EventMsg)Marshal.PtrToStructure(lParam, typeof(EventMsg));
  52.                if (wParam == 0x100)//WM_KEYDOWN=0x100
  53.                {
  54.                    barCode.VirtKey = msg.message & 0xff;//虚拟吗
  55.                    barCode.ScanCode = msg.paramL & 0xff;//扫描码
  56.                    StringBuilder strKeyName = new StringBuilder(225);
  57.                    if (GetKeyNameText(barCode.ScanCode * 65536, strKeyName, 255) > 0)
  58.                    {
  59.                        barCode.KeyName = strKeyName.ToString().Trim(new char[] { ' ', '\0' });
  60.                    }
  61.                    else
  62.                    {
  63.                        barCode.KeyName = "";
  64.                    }
  65.                    byte[] kbArray = new byte[256];
  66.                    uint uKey = 0;
  67.                    GetKeyboardState(kbArray);
  68.                    if (ToAscii(barCode.VirtKey, barCode.ScanCode, kbArray, ref uKey, 0))
  69.                    {
  70.                        barCode.Ascll = uKey;
  71.                        barCode.Chr = Convert.ToChar(uKey);
  72.                    }
  73.                    TimeSpan ts = DateTime.Now.Subtract(barCode.Time);
  74.                    if (ts.TotalMilliseconds > 50)
  75.                    {
  76.                        strBarCode = barCode.Chr.ToString();
  77.                    }
  78.                    else
  79.                    {
  80.                        if ((msg.message & 0xff) == 13 && strBarCode.Length > 3)
  81.                        {
  82.                            barCode.BarCode = strBarCode;
  83.                            barCode.IsValid = true;
  84.                         }
  85.                         strBarCode += barCode.Chr.ToString();
  86.                     }
  87.                     barCode.Time = DateTime.Now;
  88.                     if (BarCodeEvent != null) BarCodeEvent(barCode);//触发事件
  89.                     barCode.IsValid = false;
  90.                 }
  91.             }
  92.             return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
  93.         }
  94.         //安装钩子
  95.         public bool Start()
  96.         {
  97.             if (hKeyboardHook == 0)
  98.             {
  99.                 //WH_KEYBOARD_LL=13
  100.                 hKeyboardHook = SetWindowsHookEx(13, new HookProc(KeyboardHookProc), Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);
  101.             }
  102.             return (hKeyboardHook != 0);
  103.         }
  104.         //卸载钩子
  105.         public bool Stop()
  106.         {
  107.             if (hKeyboardHook != 0)
  108.             {
  109.                 return UnhookWindowsHookEx(hKeyboardHook);
  110.             }
  111.             return true;
  112.         }
  113.     }
  114. }
  115. 页面中用法:
  116. using System;
  117. using System.Collections.Generic;
  118. using System.ComponentModel;
  119. using System.Data;
  120. using System.Drawing;
  121. using System.Text;
  122. using System.Windows.Forms;
  123. namespace Common
  124. {
  125.     public partial class FrmMain : Form
  126.     {
  127.         BardCodeHooK BarCode = new BardCodeHooK();
  128.         public FrmMain()
  129.         {
  130.             InitializeComponent();
  131.             BarCode.BarCodeEvent += new BardCodeHooK.BardCodeDeletegate(BarCode_BarCodeEvent);
  132.         }
  133.         private delegate void ShowInfoDelegate(BardCodeHooK.BarCodes barCode);
  134.         private void ShowInfo(BardCodeHooK.BarCodes barCode)
  135.         {
  136.             if (this.InvokeRequired)
  137.             {
  138.                 this.BeginInvoke(new ShowInfoDelegate(ShowInfo), new object[] { barCode });
  139.             }
  140.             else
  141.             {
  142.                 textBox1.Text = barCode.KeyName;
  143.                 textBox2.Text = barCode.VirtKey.ToString();
  144.                 textBox3.Text = barCode.ScanCode.ToString();
  145.                 textBox4.Text = barCode.Ascll.ToString();
  146.                 textBox5.Text = barCode.Chr.ToString();
  147.                 textBox6.Text = barCode.IsValid? barCode.BarCode : "";//是否为扫描枪输入,如果为true则是 否则为键盘输入
  148.                 textBox7.Text += barCode.KeyName;
  149.                 //MessageBox.Show(barCode.IsValid.ToString());
  150.             }
  151.         }
  152.         //C#中判断扫描枪输入与键盘输入
  153.         //Private DateTime _dt = DateTime.Now;  //定义一个成员函数用于保存每次的时间点
  154.         //private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
  155.         //{
  156.         //    DateTime tempDt = DateTime.Now;          //保存按键按下时刻的时间点
  157.         //    TimeSpan ts = tempDt .Subtract(_dt);     //获取时间间隔
  158.         //    if (ts.Milliseconds > 50)                           //判断时间间隔,如果时间间隔大于50毫秒,则将TextBox清空
  159.         //        textBox1.Text = "";
  160.         //    dt = tempDt ;
  161.         //}
  162.         void BarCode_BarCodeEvent(BardCodeHooK.BarCodes barCode)
  163.         {
  164.             ShowInfo(barCode);
  165.         }
  166.         private void FrmMain_Load(object sender, EventArgs e)
  167.         {
  168.             BarCode.Start();
  169.         }
  170.         private void FrmMain_FormClosed(object sender, FormClosedEventArgs e)
  171.         {
  172.             BarCode.Stop();
  173.         }
  174.         private void textBox6_TextChanged(object sender, EventArgs e)
  175.         {
  176.             if (textBox6.Text.Length > 0)
  177.             {
  178.                 MessageBox.Show("条码长度:" + textBox6.Text.Length + "\n条码内容:" + textBox6.Text, "系统提示");
  179.             }
  180.         }
  181.     }
  182. }


快速回复
限100 字节
 
上一个 下一个