Search code examples
c#wpfbarcode-scanner

C# USB Barcode scanner not writing end of line char on second scan


I have a WPF application with a USB barcode scanner. The purpose of the application is for a customer to scan their customer card and enter their details automatically. At first scan after application start up, the line ends with the ENTER key and everything works as expected.

Every scan after that, i get no end of line key.

I listen for keydown on the maingrid with this code and parse the scanned input on the ENTER key. I expect a 10 char long string with an end of line ENTER but only gets the 10 chars.

The trace is only for debugging purpose.

private async void MethodWindow_KeyDown(object sender, KeyEventArgs e)
        {
            Trace.WriteLine(e.Key);
            switch (e.Key)
            {
                case Key.Enter:
                    await SwipeParser(_swipeIn);
                    _swipeIn = "";
                    break;
                default:
                    _swipeIn += GetCharFromKey(e.Key);
                    break;
            }
        }

Has anyone else experienced this? Or know another way of detecting end of line?


Solution

  • Since your question includes "know another way..." I'll offer what has worked for me: using the rate of keystrokes to tell the difference between human typing and a much-more-rapid barcode scan and of course when to know that the scan is complete.

    barcode scan

    You may have to experiment with it. I only "just now" tried porting it to WPF. But the basic idea is something that I've used reliably in my Winforms app for many years with no issues.


    WPF

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            PreviewTextInput += (sender, e) =>
            {
                foreach (char ch in e.Text)
                {
                    detectScan(ch);
                }
            };
        }
        private void detectScan(char @char)
        {
            if (_keyCount == 0) _buffer.Clear();
            int charCountCapture = ++_keyCount;
            _buffer.Append(@char);
            Task
                .Delay(TimeSpan.FromSeconds(SECONDS_PER_CHARACTER_MIN_PERIOD))
                .GetAwaiter()
                .OnCompleted(() =>
                {
                    if (charCountCapture.Equals(_keyCount))
                    {
                        _keyCount = 0;
                        if (_buffer.Length > SCAN_MIN_LENGTH)
                        {
                            Application.Current.Dispatcher.Invoke(() => 
                            {
                                var barcode = _buffer.ToString().Trim();
                                // Optional remove from currently focused textbox.
                                if(Keyboard.FocusedElement is TextBox textBox && textBox.Text.Contains(barcode)) 
                                {
                                    textBox.Text = textBox.Text.Replace(barcode, string.Empty);
                                }
                                MessageBox.Show(barcode);
                            });
                        }
                    }
                });
        }
        private readonly StringBuilder _buffer = new StringBuilder();
        int _keyCount = 0;
        const int SCAN_MIN_LENGTH = 8;
        const double SECONDS_PER_CHARACTER_MIN_PERIOD = 0.1;
    }