C# WinForm + Barcode Scanner input, TextChanged Error

19,552

Solution 1

I´m not exactly sure what the actual problem is.

txtBoxCatchScanner.Clear();
txtBoxCatchScanner.Text = "";

both trigger the "Changed" Event. But they also clear the box. So that should be what you want to do.

You could check at the beginning if the box is actually empty, and return in case it is. Like:

if(txtBoxCatchScanner.Text == "" |txtBoxCatchScanner.Text == string.Empty)
return;

So nothing else happens, if the box is empty.

If I misunderstood your problem, please specify and I will try to help.

Regards

EDIT:

Your function should work if it looked something like this:

    private void txtBoxCatchScanner_TextChanged(object sender, EventArgs e)
{             
Member member = new Member();
member.FirstName = "";
member.LastName = "";            

if(txtBoxCatchScanner.Text == "" | txtBoxCatchScanner.Text == string.Empty)
return;    // Leave function if the box is empty

//Get BarCode
//VALIDATE: Is a Number           
int numTest = 0;
if (int.TryParse(txtBoxCatchScanner.Text, out numTest))
{
    //IS A NUMBER
    //member.MemberID = Convert.ToInt32(txtBoxCatchScanner.Text);
    member.MemberID = numTest; // you already converted to a number...
    //SEARCH
    //Search Member by MemberID (barcode)
    List<Member> searchMembers = Search.SearchForMember(member);

    if (searchMembers.Count == 0)
    {
        lblAlert.Text = "No Member Found";
    }
    else
    {
        foreach (Member mem in searchMembers)
        {
            lblMemberStatus.Text = mem.MemberStatus;
            lblMemberName.Text = mem.FirstName + " " + mem.LastName;
            lblMemberID.Text = mem.MemberID.ToString();

            lblMessages.Text = mem.Notes;

            if (mem.MemberStatus == "OVERDUE") // OR .. OR .. OR ...
            {
                lblAlert.Visible = true;
                lblAlert.Text = "!! OVERDUE !!";

                //PLAY SIREN aLERT SOUND
                //C:\\WORKTEMP\\siren.wav
                SoundPlayer simpleSound = 
                    new SoundPlayer(@"C:\\WORKTEMP\\siren.wav");
                simpleSound.Play();
            }
            else
            {
                lblAlert.Visible = true;
                lblAlert.Text = mem.MemberStatus;
            }
        }
    }
}
else
{
    //IS NOT A NUMBER
    lblAlert.Text = "INVALID - NOT A NUMBER";                

    ////
    //lblMemberName.Text = "";
    //lblMemberID.Text = "";
    //lblMemberID.Text = "";
}
txtBoxCatchScanner.Clear();
}

Solution 2

The barcode scanner you use seems to function as a HID - a keyboard emulation. Every simple barcode scanner I know (and I'm working with them on a daily basis) has the option of specifying a suffix for the scanned barcode. Change the suffix to CRLF and add a default button to your form. Scanning a barcode that ends with CRLF will then automatically "push the button".

Move the code that performs the checks from TextChanged event in to the event handler for the buttons Click event and remove the TextChanged event handler. Then, when the button is clicked, also clear the text box and set the focus back to the text box.

You should be good to go, now.

You can easily check whether the barcode scanner already has the correct suffix configured: Open up Notepad and scan some barcodes. If they all appear on separate lines, then everything's fine. Otherwise you'll need to scan some configuration barcodes from the scanner's manual.

To sum it all up, this should be the code for the button's Click event:

private void btnCheckMember_Click(object sender, EventArgs e)
{             
    Member member = new Member();
    member.FirstName = "";
    member.LastName = "";            

    string memberText = txtBoxCatchScanner.Text.Trim();
    txtBoxCatchScanner.Text = String.Empty;

    int numTest = 0;
    if (String.IsNullOrEmpty(memberText) ||!Int32.TryParse(memberText, out numTest))
    {
        //IS NOT A NUMBER
        lblAlert.Text = "INVALID - NOT A NUMBER";                
        return;
    }

    member.MemberID = numTest;
    List<Member> searchMembers = Search.SearchForMember(member);

    if (searchMembers.Count == 0)
    {
        lblAlert.Text = "No Member Found";
    }
    else
    {
        foreach (Member mem in searchMembers)
        {
            lblMemberStatus.Text = mem.MemberStatus;
            lblMemberName.Text = mem.FirstName + " " + mem.LastName;
            lblMemberID.Text = mem.MemberID.ToString();

            lblMessages.Text = mem.Notes;

            if (mem.MemberStatus == "OVERDUE") // OR .. OR .. OR ...
            {
                lblAlert.Visible = true;
                lblAlert.Text = "!! OVERDUE !!";

            SoundPlayer simpleSound = new SoundPlayer(@"C:\\WORKTEMP\\siren.wav");
            simpleSound.Play();
        }
        else
        {
            lblAlert.Visible = true;
            lblAlert.Text = mem.MemberStatus;
        }
    }
}

This solution avoids the following problems:

  1. The event being triggered upon every character added/removed from the content of the text box (which is also the case when scanning a barcode: They are added one by one as if they were entered on a keyboard)
  2. Resulting from 1. the problem that a member check is performed upon every entered character
  3. Resulting from 2. the problem that member XYZ will never be found if there is a member XY in the database, as the check stops after finding XY
  4. Resulting from 3. the problem that member XY will also not be found, but only member Z, because in 3. the text box is cleared and Z is the only character being entered.

Solution 3

The best way to clear the textBox on the next textChange event.

Insert this line

txtBoxCatchScanner.SelectAll();

at the end of TextChange function.. This will select the text, so that i can be replaced easily on the next event.

Share:
19,552
user1994097
Author by

user1994097

Beginner Software Developer / Programmer. Appreciate the help! =]

Updated on June 25, 2022

Comments

  • user1994097
    user1994097 about 2 years

    UPDATE: SOLUTION AT END


    I have a Winform, label1 will display some info returned from a SQL Search using the input (MemberID) received from barcode scanner via txtBoxCatchScanner.

    Scenario is people swiping their MemberID Cards under the scanner as they pass through reception and the Winform automatically doing a Search on that MemberID and returning their info including for example "Expired Membership" etc on the receptionist's PC which has the winForm in a corner of her desktop.

    I have the Below Code working fine on first swipe (eg. first person)

    The number MemberID, for example 00888 comes up in the text box, ADO.NET pulls the data from SQL and displays it fine.

    one thing to note maybe, the cursor is at the end of the memberID: 00888|

    All good so far, THEN:

    when swipe 2 (eg. next person) happens

    their number (say, 00999) gets put onto the end of the first in the txtBox eg: 0088800999 so naturally when TextChanged Fires it searches for 0088800999 instead of 00999 ....

    I've tried:

    txtBoxCatchScanner.Clear();
    

    and

    txtBoxCatchScanner.Text = "";
    

    and reloading the form

    at the end of my code to "refresh" the text box

    but i guess they trigger the TextChanged Event

    How can i refocus or ... clear the old number and cursor back to start of txtBox after the previous swipe has done its stuff...

    I'm a beginner so I'm sure the code below is pretty crap....

    But if anyone has time, please let me know how fix it to do what i want.

    UPDATE:

    Ok after much experimenting I''ve managed to get this 1/2 working now hopefully someone more experience can help me to completion! :P

    if (txtBoxCatchScanner.Text.Length == 5)
    {
    label1.Text = txtBoxCatchScanner.Text; // just a label for testing .. shows the memmber ID
    txtBoxCatchScanner.Select(0, 5);
    }
    

    SO scan 1, say 00888 , then that gets highlighted, scan 2 , say 00997 ... sweet! overwrites (not appends to) 00888 and does it's thing ... scan 2 0011289 ... DOH!!

    Problem: not all barcodes are 5 digits!! they are random lengths!! Memeber ID range from 2 digit (eg. 25) to 10 digits, and would grow in the future...

    Edit: Something I've discovered that is that the barcodes are read as indvidual key presses. I think this is why answer 1 below does not work and while the big probmlems:

    for example with 00675 the input (?output) from the scanner is:

    Down: Do Up: Do Down: Do Up: Do Down: D6 Up: D6 Down: D7 Up: D7 Down: D5 Up: D5 down: Retunn Up: Return

    other info: barcode scanner is: an Opticon OPL6845 USB

    Thanks

    private void txtBoxCatchScanner_TextChanged(object sender, EventArgs e)
    {             
        Member member = new Member();
        member.FirstName = "";
        member.LastName = "";            
    
        //Get BarCode
        //VALIDATE: Is a Number           
        double numTest = 0;
        if (Double.TryParse(txtBoxCatchScanner.Text, out numTest))
        {
            //IS A NUMBER
            member.MemberID = Convert.ToInt32(txtBoxCatchScanner.Text);
    
            //SEARCH
            //Search Member by MemberID (barcode)
            List<Member> searchMembers = Search.SearchForMember(member);
    
            if (searchMembers.Count == 0)
            {
                lblAlert.Text = "No Member Found";
            }
            else
            {
                foreach (Member mem in searchMembers)
                {
                    lblMemberStatus.Text = mem.MemberStatus;
                    lblMemberName.Text = mem.FirstName + " " + mem.LastName;
                    lblMemberID.Text = mem.MemberID.ToString();
    
                    lblMessages.Text = mem.Notes;
    
                    if (mem.MemberStatus == "OVERDUE") // OR .. OR .. OR ...
                    {
                        lblAlert.Visible = true;
                        lblAlert.Text = "!! OVERDUE !!";
    
                        //PLAY SIREN aLERT SOUND
                        //C:\\WORKTEMP\\siren.wav
                        SoundPlayer simpleSound = 
                            new SoundPlayer(@"C:\\WORKTEMP\\siren.wav");
                        simpleSound.Play();
                    }
                    else
                    {
                        lblAlert.Visible = true;
                        lblAlert.Text = mem.MemberStatus;
                    }
                }
            }
        }
        else
        {
            //IS NOT A NUMBER
            lblAlert.Text = "INVALID - NOT A NUMBER";                
    
            ////
            //lblMemberName.Text = "";
            //lblMemberID.Text = "";
            //lblMemberID.Text = "";
        }
    

    SOLUTION:

    The System won't let me answer my own question for another 3 hours, as I'm a newbie only 1 post, so will put here:

    First thanks everyone for your help and Patience.

    I Have finally figured a solition, not fully tested yet as its 2am and bed time.

    following along from my updates where I had success but hit the variable length of MemberID problem. I've now overcome that with the Code below:

    namespace SCAN_TESTING
    {
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    
        private void txtBoxCatchScanner_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyValue == (char)Keys.Return)
            {
                e.Handled = true;
    
                int barcodeLength = txtBoxCatchScanner.TextLength;
    
                txtBoxCatchScanner.Select(0, barcodeLength);
    
                //TEST
                label3.Text = barcodeLength.ToString();
                //TEST
                label2.Text = txtBoxCatchScanner.Text;
    
            }
    
        }
    

    I'll add this to my previous "real" code and test in the morning But at this stage is doing exactly what I want! =]

    Update: Tested it .. works exactly what needed:

    private void txtBoxCatchScanner_KeyUp(object sender, KeyEventArgs e)
    {
       if (e.KeyValue == (char)Keys.Return)
          {
                e.Handled = true;
    
                int barcodeLength = txtBoxCatchScanner.TextLength;
    
                txtBoxCatchScanner.Select(0, barcodeLength);
    
               //
               //INSERT ORGINAL CODE HERE. No Changes were needed.
               //
    
    
          }//end of if e.KeyValue ...
    }//end txtBoxCatchScanner_KeyUp
    

    Hope that helps anyone in the future!! :)

    Thanks again for the 2 very good solutions, I can see how they work, and learnt alot. Just didn't work in my case - more likely due to myself or my error/not understanding, or scanner type.

    • default
      default over 11 years
      @Soner Gönül: why did you increase the indenting when you could have removed it?
    • Admin
      Admin over 11 years
      The code that will have the issue will be the code where you assign the text to the textbox, could you show us that bit rather than the text changed event?
    • Admin
      Admin over 11 years
      P.s also in your final else, you set the alert text to not a number, but you dont make the label visible
    • user1994097
      user1994097 over 11 years
      Sorry have no idea what you mean about indenting... RhysW ... there is no other code at all apart from the public void FormScanner_Load and Public FormScanner()
    • Admin
      Admin over 11 years
      Ok in which case can you show me the section of code where you set the textbox's text to 00888 etc please?
    • user1994097
      user1994097 over 11 years
      the text for the textbox comes from the barcode scanner and is this part: //IS A NUMBER member.MemberID = Convert.ToInt32(txtBoxCatchScanner.Text); ... if that helps
    • Admin
      Admin over 11 years
      where is the code where you do for example txtBoxCatchScanner.Text = 00889; or is that happening from a third party?
    • Uwe Keim
      Uwe Keim over 11 years
      @Default I've removed the indent :-)
    • user1994097
      user1994097 over 11 years
      the membership barcode is swiped (eg. 00889) scanner input goes to txtBoxCatchScanner which triggers TextChanged ... txtBoxCatchScannerText get's its imput from the barcode scanner .....
    • Admin
      Admin over 11 years
      ok so it gets its input from the scanner, can you show me that code where you get the information from the scanner and put it in the textbox, i cant help you solve the issue without seeing the code
    • user1994097
      user1994097 over 11 years
      there is no other code. scanner goes into usb port... scan barcode ... barcode appears in txtbox ... the code i posted above is the complete all there is code... apart from the namespace, page load etc.. there is no other code. sorry, thanks anyways.
    • Admin
      Admin over 11 years
      Ok but the barcode doesnt doesnt magically appear in the textbox, somewhere somehow a piece of code is setting the text in that textbox, does your code set the textbox to be the numbers or is this a third party windows form?
    • user1994097
      user1994097 over 11 years
      Soner & Uwe: thanks for that, see what u mean now :P ... sorry about that, first time post.
    • default
      default over 11 years
      @UweKeim thanks! :) looks much better
    • Thorsten Dittmar
      Thorsten Dittmar over 11 years
      @RhysW: Yes it does, if the scanner is configured as a USB keyboard, which most simple barcode scanners are by default.
    • Thorsten Dittmar
      Thorsten Dittmar over 11 years
      I just read that the member IDs have variable length: What happens if you have a member 12 and a member 121? If you have one event after each character (which is the case with the TextChanged event - the scanner works like typing one character after the other, so after every digit, TextChanged is triggered), you will never see member 121, as you stop after finding member 12. Do not use TextChanged! See my approach for a clean and working solution.
    • Admin
      Admin over 11 years
      @ThorstenDittmar i was trying to disscern if he had access to the code that did it or not, and no it doesn tmagically appear, there is code for it, and i was trying to find out if he had access to it
    • Thorsten Dittmar
      Thorsten Dittmar over 11 years
      @RhysW: Yes, there is code for it. In the scanner's keyboard driver, or the generic Windows USB keyboard driver which is most probably used to handle such devices.
    • Admin
      Admin over 11 years
      @ThorstenDittmar precisely! I wasnt aware if he had access to that though hence my many questions :)
    • Thorsten Dittmar
      Thorsten Dittmar over 11 years
      @RhysW: It's just that some people tend to forget keyboard emulation when working with COM connected scanners too long. :-)
    • Admin
      Admin over 11 years
      @ThorstenDittmar Very True, also the solution you provided is very good, avoids more problems than just the one addressed
  • Admin
    Admin over 11 years
    The actual problem is that at some point the new numbers are appended to the old numbers instead of overwriting them, the setting it to blank at the end was a workaround for that, and this solution is now a workaround for the workaround XD
  • user1994097
    user1994097 over 11 years
    hmms the problem is, if I do txtBoxCatchScanner.Clear()/etc it triggers TextChanged which then triggers a Search for memberID "" <-- i guess a "space" of which there is of course 1. not a number and 2. no member with ID of [space] and so the reponse is "Invalid number", "no member found"
  • Admin
    Admin over 11 years
    @User1994097 Yeah because clearing it is a text changed event, but somewhere in your code you must be setting that textbox to be the numbers from the scanner, at this point of the code there is an error where instead of overwriting the old number with the new one you are appending it, which gives you the long number, i can solve the issue for you but for this you need to show the code where you SET the text box text to the numbers
  • user1994097
    user1994097 over 11 years
    somewhere in your code you must be setting that textbox to be the numbers from the scanner - No .. the way a barcode scanner works is: scan a barcode and it spits out the number into whatever is in focus ... open a .txt and have the cursor there and it will spit out the number to it.. have an .xls open and the cursor in a cell ... it will spit out to that cell... or in this case ... have a winform open with cursor in the textbox (?"in focus) it spits it to that textbox there is not code ... it is not like a click event ....
  • Admin
    Admin over 11 years
    @user1994097 ok see now that piece of information would have been useful right from the very beginning, in which case this answer we are commenting on is probably the best solution, as its told that when there is a text changed event to check there is text, so this will ignore the empty "" sections
  • user1994097
    user1994097 over 11 years
    I assumed you know how a barcode scanner worked, but I should been clearer sorry. Sadly this solution doesn't work
  • Nicolas
    Nicolas over 11 years
    I edited my above post. The box now gets cleared after the function completed. Which triggers the function again but immediately exits due to the "if(bla = "" |bla == string.Empty)" stuff.
  • Thorsten Dittmar
    Thorsten Dittmar over 11 years
    @user1994097 To RhysW's credit it should be noted that not all barcode scanners work this way. The more expensive ones can also be configured to use COM port emulation. You'd then need to open the respective COM port and retrieve information from there. This is also the preferred way, because problems as the one you're having only arise when using the keyboard wedge feature.
  • user1994097
    user1994097 over 11 years
    Nicolas thanks, i'll give it a go. I've also updated my post with a minir lead... will try your solution now. @Thorsten: thanks for the info, and appreciate RjysW's attempt. Cheers
  • user1994097
    user1994097 over 11 years
    Thanks I'll give this answer1 ago and let you guyes know. Many Thanks
  • Thorsten Dittmar
    Thorsten Dittmar over 11 years
    Sorry to say that, but you really should not be using the TextChanged event! This is a bad idea, as it is called whenever you edit the text - also if the user manually enters text. That means that upon every character you add through keyboard or scanner, one event is triggered, causing a validation of the member id. DON'T! I don't want to overly advertise my approach, but it is much cleaner...
  • Thorsten Dittmar
    Thorsten Dittmar over 11 years
    I just read that the member IDs have variable length: What happens if you have a member 12 and a member 121? If you have one event after each character, you will never see member 121, as you stop after finding member 12. Do not use TextChanged!
  • Thorsten Dittmar
    Thorsten Dittmar over 11 years
    No problem. Please make sure using Notepad (or even the Visual Studio editor) that every scan is put on a separate line first - otherwise the button will not get "pressed" and you need to configure the suffix first.
  • user1994097
    user1994097 over 11 years
    I'll have to look into the scanner and how to "Change the suffix to CRLF" ... this scanner just plugs into the usb port and uses some kind of generic windows drivers I guess .. there not drivers supplied for it. Will try tomorrow. Thanks for help and patience everybody!
  • Thorsten Dittmar
    Thorsten Dittmar over 11 years
    What happens if you just scan? Are the barcodes appended in one line? For simple gun scanners, things like that are configured using special configuration barcodes. There's no special driver - they are "Generic HID devices" (Human Interface Device). Usually there's a sequence of special barcodes, like "Start Configuration" -> "Change Suffix" -> "Scan ASCII codes for suffix" -> "Finish configuration.
  • user1994097
    user1994097 over 11 years
    thanks. this is what the scanner outputs atm: for example with 00675 the input (?output) from the scanner is: Down: Do Up: Do Down: Do Up: Do Down: D6 Up: D6 Down: D7 Up: D7 Down: D5 Up: D5 down: Return Up: Return
  • Thorsten Dittmar
    Thorsten Dittmar over 11 years
    Seems you already get the CRLF. To make sure: close all programs, start Notepad and scan multiple times. Do the barcodes appear on separate lines? Alternatively: Add a button to the form, assign it's Click handler showing a MessageBox, set the form's AcceptButton property to the new button and then run and scan - do you see the MessageBox? If so, everything's fine already.
  • user1994097
    user1994097 over 11 years
    doesn't appear this scanner can do the suffix change thing. old.opticon.com/… will investigate tomorrow. nites all . thanks
  • Thorsten Dittmar
    Thorsten Dittmar over 11 years
    As I said: most probably CRLF is already present, as you can see the last key pressed and released by the scanner is RETURN.
  • user1994097
    user1994097 over 11 years
    Have Solved the problem. Thanks for your help! Will post solution.
  • user1994097
    user1994097 over 11 years
    Have Solved the problem. Thanks for the help guys. WIll Post the solution