C#条形码扫描程序将不接受字母字符

时间:2019-04-05 14:14:18

标签: c# keypress barcode-scanner

我有一些用C#编写的代码,允许用户扫描条形码和标签。文本更改为条形码的输入。我使用标签而不是文本框来防止用户用手指乱写错误的条形码-基本上禁用了任何键盘输入。

除扫描的条形码中包含字母字符外,其他所有方法均正常运行。如果条形码以字母字符开头并以字母字符结尾,则条形码根本不会扫描。

如果条形码以字母字符开头,但以数字字符结尾,则程序仅选择尾随的数字字符。

代码如下:

    char cforKeyDown = '\0';
    int _lastKeystroke = DateTime.Now.Millisecond;
    List<char> _barcode = new List<char>();
    bool UseKeyboard = false;

  private void Form1_Load(object sender, EventArgs e)
    {
        this.ActiveControl = label1;
        this.KeyDown += new KeyEventHandler(Form1_KeyDown);
        this.KeyUp += new KeyEventHandler(Form1_KeyUp);
    }
 private void Form1_KeyUp(object sender, KeyEventArgs e)
    {
        // if keyboard input is allowed to read
        if (UseKeyboard && e.KeyData != Keys.Enter)
        {
            MessageBox.Show(e.KeyData.ToString());
        }

        /* check if keydown and keyup is not different
         * and keydown event is not fired again before the keyup event fired for the same key
         * and keydown is not null
         * Barcode never fired keydown event more than 1 time before the same key fired keyup event
         * Barcode generally finishes all events (like keydown > keypress > keyup) of single key at a time, if two different keys are pressed then it is with keyboard
         */

        if (cforKeyDown != (char) e.KeyCode || cforKeyDown == '\0')
        {
            cforKeyDown = '\0';
            _barcode.Clear();
            return;
        }

        // getting the time difference between 2 keys
        int elapsed = (DateTime.Now.Millisecond - _lastKeystroke);

        /*
         * Barcode scanner usually takes less than 17 milliseconds to read, increase this if neccessary of your barcode scanner is slower
         * also assuming human can not type faster than 17 milliseconds
         */
        // Bumped it up to 35[ms]
        if (elapsed > 50)
            _barcode.Clear();

        // Do not push in array if Enter/Return is pressed, since it is not any Character that need to be read
        if (e.KeyCode != Keys.Return)
        {
            //_barcode.Add((char) e.KeyData);
            _barcode.Add((char) e.KeyData);
        }

        // Barcode scanner hits Enter/Return after reading barcode
        if (e.KeyCode == Keys.Return && _barcode.Count > 0)
        {
            string BarCodeData = new String(_barcode.ToArray());

            if (!UseKeyboard)
            {
                //MessageBox.Show(String.Format("{0}", BarCodeData));
                label1.Text = String.Format("{0}", BarCodeData);
            }
            //_barcode.Clear();
        }
        // update the last key stroke time
        _lastKeystroke = DateTime.Now.Millisecond;
    }

    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        //Debug.WriteLine("CS_Single_Label_Printer_KeyDown : " + (char)e.KeyCode);
        cforKeyDown = (char) e.KeyCode;
    }

我将问题缩小为以下事实:所扫描的字母数字条形码的字母部分为大写。我使用小写字母生成了测试条形码,并且一切正常进行,但这仍然无法解决问题,因为我必须扫描成千上万已打印的条形码,这些条形码中的大写字符已编码到条形码数据矩阵中。 >

是否有一种方法可以切换以上代码,以解决“字符| Shift'KeyData?

1 个答案:

答案 0 :(得分:1)

答案是KeyCode返回按下的KEY。它不尊重密钥的大小写。使用Shift获取案例。以下是基于您提供的代码的工作示例。魔术在本地函数ToCharacter中。如果您愿意,还需要使用顶部的if语句来包含数字。

From1.cs

using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace DesktopApp2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        char cforKeyDown = '\0';
        int _lastKeystroke = DateTime.Now.Millisecond;
        List<char> _barcode = new List<char>();
        bool UseKeyboard = false;

        private void Form1_Load(object sender, EventArgs e)
        {
            this.ActiveControl = InputBox;
            this.InputBox.KeyDown += new KeyEventHandler(Form1_KeyDown);
            this.InputBox.KeyUp += new KeyEventHandler(Form1_KeyUp);
        }
        private void Form1_KeyUp(object sender, KeyEventArgs e)
        {
            char NotALetter = '-';

            DebugBox.Items.Clear();
            DebugBox.Items.Add($"KeyEventArgs->KeyCode = {e.KeyCode.ToString()}");
            DebugBox.Items.Add($"KeyEventArgs->KeyData = {e.KeyData.ToString()}");
            DebugBox.Items.Add($"KeyEventArgs->KeyValue = {e.KeyValue.ToString()}");
            DebugBox.Items.Add($"KeyEventArgs->e.Shift = {e.Shift.ToString()}");
            DebugBox.Items.Add($"ToCharacter = {ToCharacter(e) ?? NotALetter}");


            char? ToCharacter(KeyEventArgs kea)
            {
                int DtoNumPadOffset = (int)(Keys.NumPad0 - Keys.D0);
                if (kea.KeyCode < Keys.D0) return null; // Keys.D0 through Kyes.D9 are the Keys on the top row of the keyboard. D9 is right next to A in the enum type. 
                if (kea.KeyCode > Keys.NumPad9) return null;
                if (kea.KeyCode > Keys.Z && kea.KeyCode < Keys.NumPad0) return null; //knocks out keys between Z and NumPad0
                if (kea.Shift && kea.KeyCode < Keys.A) return null; // rejects special characters when numbers across the top are used with the <shift> key.

                if (kea.KeyCode < Keys.A) return (char)kea.KeyCode;
                if (kea.KeyCode > Keys.Z) return (char)((int)kea.KeyCode - DtoNumPadOffset);

                return kea.Shift
                    ? (char)kea.KeyCode
                    : char.ToLower((char)kea.KeyCode);
            }


            // if keyboard input is allowed to read
            if (UseKeyboard && e.KeyData != Keys.Enter)
            {
                MessageBox.Show(e.KeyData.ToString());
            }

            /* check if keydown and keyup is not different
             * and keydown event is not fired again before the keyup event fired for the same key
             * and keydown is not null
             * Barcode never fired keydown event more than 1 time before the same key fired keyup event
             * Barcode generally finishes all events (like keydown > keypress > keyup) of single key at a time, if two different keys are pressed then it is with keyboard
             */

            //if (cforKeyDown != (char)e.KeyCode || cforKeyDown == '\0')
            //{
            //    cforKeyDown = '\0';
            //    _barcode.Clear();
            //    return;
            //}

            // getting the time difference between 2 keys
            int elapsed = (DateTime.Now.Millisecond - _lastKeystroke);

            /*
             * Barcode scanner usually takes less than 17 milliseconds to read, increase this if neccessary of your barcode scanner is slower
             * also assuming human can not type faster than 17 milliseconds
             */
            // Bumped it up to 35[ms]
            //if (elapsed > 2000)
            if (e.KeyCode == Keys.Return)
            {
                InputBox.Text = String.Empty;
                _barcode.Clear();
            }

            // Do not push in array if Enter/Return is pressed, since it is not any Character that need to be read
            if (e.KeyCode != Keys.Return)
            {
                char? TestForCharacter = ToCharacter(e);

                if (TestForCharacter != null)
                {
                    //_barcode.Add((char) e.KeyData);
                    _barcode.Add((char)TestForCharacter);
                }
            }

            OutputBox.Text = string.Concat(_barcode);

            // Barcode scanner hits Enter/Return after reading barcode
            if (e.KeyCode == Keys.Return && _barcode.Count > 0)
            {
                string BarCodeData = new String(_barcode.ToArray());

                if (!UseKeyboard)
                {
                    //MessageBox.Show(String.Format("{0}", BarCodeData));
                    OutputBox.Text = String.Format("{0}", BarCodeData);
                }
                //_barcode.Clear();
            }
            // update the last key stroke time
            _lastKeystroke = DateTime.Now.Millisecond;
        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            //Debug.WriteLine("CS_Single_Label_Printer_KeyDown : " + (char)e.KeyCode);
            cforKeyDown = (char)e.KeyCode;
        }
    }
}

Form1.Designer.cs

namespace DesktopApp2
{
    partial class Form1
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.OutputBox = new System.Windows.Forms.TextBox();
            this.InputBox = new System.Windows.Forms.TextBox();
            this.DebugBox = new System.Windows.Forms.ListBox();
            this.SuspendLayout();
            // 
            // OutputBox
            // 
            this.OutputBox.Location = new System.Drawing.Point(52, 93);
            this.OutputBox.Name = "OutputBox";
            this.OutputBox.ReadOnly = true;
            this.OutputBox.Size = new System.Drawing.Size(650, 22);
            this.OutputBox.TabIndex = 1;
            // 
            // InputBox
            // 
            this.InputBox.Location = new System.Drawing.Point(52, 45);
            this.InputBox.Name = "InputBox";
            this.InputBox.Size = new System.Drawing.Size(650, 22);
            this.InputBox.TabIndex = 2;
            // 
            // DebugBox
            // 
            this.DebugBox.FormattingEnabled = true;
            this.DebugBox.ItemHeight = 16;
            this.DebugBox.Location = new System.Drawing.Point(52, 131);
            this.DebugBox.Name = "DebugBox";
            this.DebugBox.Size = new System.Drawing.Size(650, 308);
            this.DebugBox.TabIndex = 3;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(716, 450);
            this.Controls.Add(this.DebugBox);
            this.Controls.Add(this.InputBox);
            this.Controls.Add(this.OutputBox);
            this.Name = "Form1";
            this.Text = "Form1";
            this.Load += new System.EventHandler(this.Form1_Load);
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion
        private System.Windows.Forms.TextBox OutputBox;
        private System.Windows.Forms.TextBox InputBox;
        private System.Windows.Forms.ListBox DebugBox;
    }
}

用于处理KeyEventArgs的简洁助手类
Is *函数将键控代码分为多个范围,并检测(如果适用)移位状态。 To *函数产生最能代表事件中KeyCode的字符。 ToAlphaNumericAsciiCharacter只需将检测器与生产者配对即可。

public static class KeyEventArgs_Functions
{
    public static bool Between(this Keys source, Keys lhv, Keys rhv)
    {
        return source >= lhv && source <= rhv;
    }
    public static bool IsLetterKeyBoardChar(this KeyEventArgs source)
    {
        return source.KeyCode.Between(Keys.A, Keys.Z);
    }
    public static bool IsNumberKeyBoardChar(this KeyEventArgs source)
    {
        return !source.Shift && source.KeyCode.Between(Keys.D0, Keys.D9);
    }
    public static bool IsNumber10KeyPadChar(this KeyEventArgs source)
    {
        return source.KeyCode.Between(Keys.NumPad0, Keys.NumPad9);
    }
    public static char ToLetterKeyBoardChar(this KeyEventArgs source) // Only returns a valid value if IsLetterKeyBoardChar returns true.
    {
       return source.Shift ? (char)source.KeyCode: char.ToLower((char)source.KeyCode);
    }
    public static char ToNumberKeyBoardChar(this KeyEventArgs source) // Only returns a valid value if IsNumberKeyBoardChar returns true.
    {
        return (char)source.KeyCode;
    }
    public static char ToNumber10KeyPadChar(this KeyEventArgs source) // Only returns a valid value if IsNumber10KeyPadChar returns true.
    {
        const int DtoNumPadOffset = (int)(Keys.NumPad0 - Keys.D0);
        return (char)((int)source.KeyCode - DtoNumPadOffset);
    }
    public static char? ToAlphaNumericAsciiCharacter(this KeyEventArgs source)
    {
        if (source.IsLetterKeyBoardChar()) return source.ToLetterKeyBoardChar();
        if (source.IsNumberKeyBoardChar()) return source.ToNumberKeyBoardChar();
        if (source.IsNumber10KeyPadChar()) return source.ToNumber10KeyPadChar();
        return null;
    }
}