Display a messagebox without a default button

Pyth007

Member
Joined
Nov 17, 2008
Messages
18
Programming Experience
5-10
This is actually one of the easiest solutions that I could think of for the actual issue that I'm having...

I am trying to write a program where the user scans in a barcode on a device, and the program checks the validity of the scanned value, saves the scan in a database, and then prints out a corresponding label for the device. The REAL problem that I'm running into is that if the scan is not valid (the user scanned in the wrong barcode, the barcode has already been used and is in the database, the value scanned doesn't match the regular expression that I'm using to parse the scan, etc.) there is supposed to be an error message that pops up to let the user know what issue the program has run into. However, the problem is that the messagebox (for the error message) flashes on the screen too quickly to actually read and immediately disappears (sometimes it happens so quickly that it looks like nothing has happened at all).

I'm pretty sure that this is because the barcode reader is appending a carriage return at the end of whatever is being scanned. Usually this is a nice feature as many other programs also on that computer require the user to push enter after typing something in. So having the barcode reader automatically append that at the end saves the user from having to hit the enter key after scanning in an item. However for my application, this is causing issues since the data that the user scans in will get processed, determined that there is something invalid about it, post the messagebox, and then accepts the carriage return as the input on the messagebox, thereby executing whatever the default button on that messagebox corresponds to (for most of my error messages, this means it acts as though the "OK" button was pressed and will immediately close the messagebox window; hence why it looks like it's just flashing on the screen for a split second).

I've been trying to capture the key strokes and suppress them if they are like a carriage return, but this doesn't solve the problem (the stuff about checking for ControlKey being pushed is that some barcode readers will append a Ctrl+M to act as a carriage return)...
VB.NET:
    Private Sub txtBarcode_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles txtBarcode.KeyDown
        If ((e.KeyCode = Keys.Enter) Or (e.KeyCode = Keys.Tab) Or (e.KeyCode = Keys.Return) Or (e.KeyCode = Keys.LineFeed)) Then e.SuppressKeyPress = True
        If Me._boolCtrl Then
            Me._boolCtrl = False
            If e.KeyCode = Keys.M Then
                e.SuppressKeyPress = True
            End If
        End If
        If e.KeyCode = Keys.ControlKey Then Me._boolCtrl = True
    End Sub

If I use the PreviewKeyDown event handler, it doesn't recognize "e.SuppressKeyPress = True" since "SuppressKeyPress is not a member of PreviewKeyDownEventArgs". And since I'm using the textbox's TextChanged event handler to process the value scanned, its signature has "e As System.EventArgs" so it doesn't recognize anything (eg it doesn't recognize e.KeyCode, e.SupressKeyPress, etc.).

Because my previous attempts of trying to suppress a carriage return doesn't seem to work, I was trying to think of a different way to ensure that the user is reading the error message. I saw some posts about using a button-less modal window / form that automatically closes after a set amount of time. Although this would be interesting for most of the error messages, I do have one that uses Yes/No buttons; if a user scans in a barcode that is already in the database, it asks the user whether they want to re-print the label for that device. So the other option that I thought of using would be to display a MessageBox but would not have any of the button as default, thereby requiring the user to actually use a mouse to click on their desired answer. But unfortunately I haven't found a way to do that... I've even attempted to set the default button to button3 (thinking that since the messagebox only has 2 buttons, it wouldn't assign either as default), but the program is too smart and will assign button1 as default if it can't find the button listed.

Any ideas on how I can either stop the program from reading the appended carriage return, display a messagebox without having a button as default, or even clearing out the key-strokes buffer after it gets the data that fits the validating regular expression? I'd like to use the existing MessageBox control if at all possible so that I don't have to re-invent something like it just to display the error messages...
 

IanRyder

Well-known member
Joined
Sep 9, 2012
Messages
1,130
Location
Healing, NE Lincs, UK
Programming Experience
10+
Hi,

I have not tested this with a Barcode Scanner but have a go with this example that will only activate a validation routine if the Enter Key or CTRL+M Key is pressed:-

Public Class Form1
 
  Private Sub TextBox1_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles TextBox1.KeyDown
    If e.KeyCode = Keys.Enter OrElse (e.KeyCode = Keys.M AndAlso e.Modifiers = Keys.Control) Then
      e.SuppressKeyPress = True
      If ValidateBarCodeScan() Then
        MsgBox("I Like That Scan!")
      Else
        MsgBox("Invalid Scan!")
      End If
    End If
  End Sub
 
  Private Function ValidateBarCodeScan() As Boolean
    'Do Some Validation of what has been scanned
    If TextBox1.Text.Equals("Hello", StringComparison.InvariantCultureIgnoreCase) Then
      Return True
    Else
      Return False
    End If
  End Function
End Class


Hope that helps.

Cheers,

Ian
 

Pyth007

Member
Joined
Nov 17, 2008
Messages
18
Programming Experience
5-10
I finally solved this issue... I think I was going about this the wrong way; instead of trying to get the program to ignore the appended carriage return, I turned it around and did the processing of the scan after I got that carriage return.

What was happening was that in my TextChanged event, I was using a regular expression against the data. So when I scanned in the barcode, each character was being checked by this event and quickly would exit after setting the ErrorProvider to the textbox with an error message about the data not matching the regular expression, that is until it reached the end of the data where it would then start processing the data, including the check against the database to see if the item was already scanned in. It was here that the error message (in the form of a MessageBox) would be shown, and the appended carriage return would interact with that MessageBox. Because the MessageBox is not a part of the TextBox (nor even a part of the main form), none of the events I tried to trap that carriage return would get triggered. I even tried putting Ian's code into the form's KeyDown event (and turning on the form's KeyPreview property) to no avail since the MessageBox would accept the carriage return before the form regained control.

But in trying these other events to trap the carriage return, I hit upon the idea to essentially do the reverse by waiting to do the processing until after the textbox received the carriage return. So I took all of the code out of the textbox's TextChanged event, put it into the textbox's KeyDown event instead, and nested it under an if...then... block that would check if a carriage return key was "pressed". And even though everything was happening so quickly before, by doing this I'm thinking I also am saving a little bit of time since I'm now just checking for a carriage return first instead of comparing the entire, growing string against the regular expression.
 
Top Bottom