Программа сканирования C # BarCode не принимает буквенные символы - PullRequest
1 голос
/ 05 апреля 2019

У меня есть некоторый код, написанный на 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 Ответ

1 голос
/ 05 апреля 2019

Ответ в том, что 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;
    }
}

вспомогательный класс Tidy для работы с 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;
    }
}
...