How to read input from a barcode scanner in vb.net without using a textbox? - vb.net

My program is already working fine, I use a TextBox to capture the barcode scanner input. The purpose of my program is for time and attendance monitoring, the problem is I want to prevent users from using the keyboard to type in their ID's as it would render the barcode scanner and their ID's with barcodes useless.
*I already tried removing the keyboard from the computer and it did work, but the keyboard must not be removed as a requirement...

Option 1:
Get a barcode-scanner that is connected to a serial-port (raw serial device read by a COM port). As most barcode-scanners emulate keyboard strokes there is no way to directly distinguish a barcode scanner input from a keyboard input (see next option) without going low-level (see last update).
One connected to a serial port (or emulated one via USB as serial-ports are not so common anymore) gives you full control on where the input comes from.
Option 2:
Count number of chars typed by time. Barcode-scanners inject a sequence (line) pretty fast compared to typing. Measuring the time used in the textbox by counting key-presses (use CR+LF as a measure point as these are sent by the scanner as well) can give you one method to distinguish if a human is typing (unless there is one typing fast as f) or the content was injected. If timed-out just reject/clear the input.
In addition the checksum of the barcode (if you use one that contains that) can be used to do an extra validation in addition to time measurement.
(you can detect pasting by overriding the ctrl + v as in the next option).
Option 3:
Combine option 2 but instead of measure in the textbox tap into the ProcessCmdKey() function (by overriding it) and measure there if textbox has focus. This way you can first buffer input, measure time and if within a set time-out value, inject the line into the textbox.
Update:
Option 4: a non-technical approach -
Usability improvements: make it visually very clear that bar-codes must be entered with a scanner and not typed. I am including as an option as it is simple and if made correct also effective (there's no right answer of what is correct unfortunately).
Approached could include f.ex. a watermark in the textbox ("Don't type, scan!" or something in that order). Give it a different color, border, size etc. to distinguish it from normal textboxes, and have a help text associated and available at all time that improves clarity.

I had the same issue and I did the following:
I set an int variable digitsPrevTyped = 0
In the "TextChanged" event of my textbox I added this (the textbox has a maxsize of 17 chars):
Private Sub tbxScannedText_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles tbxScannedText.TextChanged
If tbxScannedText.Text.Length >= 17 Then
SearchFunction(False)
Else
digitsPrevTyped = tbxScannedText.Text.Length
End If
End Sub
Then in my "SearchFunction" I check the following:
Dim inputMethod As Char
If tbxScannedText.TextLength = 17 And digitsPrevTyped = 0 Then
inputMethod = TEXT_SCANNED
Else
inputMethod = TEXT_MANUALLY_ENTERED
End If
If the textbox initially had a length of 0 chars and now has a length of 17 chars it means that the text was scanned. If the length of the previously typed text is less than 17 chars, then the text was typed.
It is very basic but it works for me.

The other possible workaround is to handle keypress event to restrict user input. Do not allow direct input from keyboard and leave the readonly false.
Set following in KeyPress event handler
Private Sub Textbox1_KeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles Textbox1.KeyPress
e.Handled = True
End Sub

Just disable the keyboard anyway.. when using barcode you can disable the keyboard without using readonly on the textbox..
on keypress event put some code i.e
if e.keychar <> chrw(0) then
e.keychar = chrw(0)
end if
that condition will automatically be trigged when user type anything.. you will forcibly disable any input from user but not from barcode

why not use an "alias" in the bar code like "123##$!" (but make it stupid long) is "JSMITH" and set the font color to the same as the background color in the textbox. The user can't see what they're typing or what the bar code value is when it's scanned.
Super simplistic approach that doesn't really require anything added aside from another field in the the user table.

This is an old post, but it took me some time to figure out a relatively clean way to use a barcode scanner and combobox so this is for future users.
Barcode scanners can often be configured to append carriage return and line feed to the end of the scan. I have a form that can take user input or barcode scanner input into a bound combobox using the _PreviewKeyDown property and trapping on the value "Keys.Enter".
Example:
If ((e.KeyCode = Keys.Enter) Then
'do stuff
Else
'do other stuff
End if
Verifying the data exists in the datasource is a bit trickier because the SelectedValue property of the combobox doesn't update so that event doesn't fire. I used a custom method to verify that the value scanned exists in the datasource. This method uses the .Text property of the combo box. It uses:
Me.combobox.findexactstring(Me.combobox.Text)

If e.KeyCode = Keys.Enter And txt.Text.Length > 0 Then
'To Do
Else
'To Do
End if

All of my scanner input goes into a "hidden" textbox, which then fills the visible ones as needed depending on the input. This, of course, means you need to keep track of where the focus is. Any type of control that can get focus will then make a call in those events to return focus to whatever the "active" textbox is at that time, which is normally the hidden one. For example...
Private Sub buttons_gotFocus(sender As System.Object, e As System.EventArgs) Handles btnPrint.GotFocus, btnInMVPageDown.GotFocus, btnAdv.GotFocus, btnManual.GotFocus, btnResend.GotFocus, dgvInbound.GotFocus, dgvOutbound.GotFocus, TCRole.GotFocus
Try
activeTextbox.Focus()
Catch ex As Exception
'ignore any errors
End Try
End Sub
Most other textboxes are disabled by default, and only enabled under certain conditions. Once that entry is done they are disabled and the hidden one will get focus again. Works like a charm.

There's no need to record previous typed characters.
Here's my solution:
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
If TextBox1.Text.Length >= 17 Then '17 or the number of characters your scanner gets.
MsgBox("scanned")
TextBox1.Clear()
Else
If TextBox1.Text.Length <> 0 Then TextBox1.Clear()
End If
End Sub

This answer will handle any fast typing.
Dim scanner_input As Boolean = False
Dim start_typing As DateTime
Private Sub TextBox_part_number_TextChanged(sender As Object, e As EventArgs) Handles
TextBox_part_number.TextChanged
If (TextBox_part_number.Text.Length = 1) Then
start_typing = DateTime.Now
scanner_input = False
'' MsgBox(start_typing.ToString)
ElseIf (TextBox_part_number.Text.Length > 7) Then
If (calc_typing_time(start_typing) < 500) Then
scanner_input = True
Else
scanner_input = False
End If
End If
End Sub
Function calc_typing_time(time_started As DateTime)
Dim time_finished As DateTime
time_finished = DateTime.Now
Dim duration As TimeSpan = time_finished - time_started
Dim time_diff As String = duration.TotalMilliseconds
Return time_diff
End Function

Most of the scanners has a driver to communicate with (Opos) it has functions to open the scanner port and listen to the scanning , so you take the result and decode it in the background and then display the result in the Textbox... what you need to do it to check your barcode scanner's brand go to it's website and download the driver and its manual.

You should just mark your textbox as readonly.

Related

How can cancelling DataGridViewCellValidatingEventArgs replace all event handlers with itself?

I'm having a very strange problem in a VB application. I have a function written like this:
In the innermost condition, two statements are commented out here. These were found to have no effect on the strange behaviour. This is the minimal example I've found causing trouble.
(Note that the names of objects have been changed in this example.)
Private Sub MyForm_CellValidating(ByVal sender As Object, ByVal e As DataGridViewCellValidatingEventArgs) Handles myDGV.CellValidating
Dim dgv As DataGridView = CType(sender, DataGridView)
Select Case dgv.Columns(e.ColumnIndex).Name
Case "uniqueColumn"
' Validate that the values in our unique column are unique.
For i As Integer = 0 To dgv.RowCount - 1
If i <> e.RowIndex Then
' Here i != j, so compare to the value...
If e.FormattedValue = dgv.Rows(i).Cells(e.ColumnIndex).FormattedValue Then
e.Cancel = True
'dgv.ShowRowErrors = True
'dgv.Rows(e.RowIndex).ErrorText = "Data in the unique column must be unique"
End If
End If
Next 'i
Case Else
' Perform no validation.
End Select
End Sub
What trouble, you ask? For some inexplicable reason, whenever the line
e.Cancel = True
is executed, afterwards, nearly all buttons and form widgets in the entire application, including even the close button in its window bar (what a user would use to exit the application) stop doing whatever they previously did and now call this event handler instead.
In other words, commenting out that line (and doing the validation manually when the form is submitted) fixes the problems. I'd like to know why this happens, though. Some pointers:
Here's a list of which things are not affected:
The minimize and maximize button in the top bar.
All objects in its menu bar.
This handler is private to its form class, it's not referenced anywhere else in the application.
I'm at a loss. Just how? What could possibly cause this?
e.Cancel is for stopping the validation when the input is deemed incorrect. This causes the cell to still have focus as the user is expected to correct whatever they did wrong. The CellValidating event will then be raised again whenever the cell is about to lose focus until your code deems the input to be correct.
You can use the Control.CausesValidation property to control whether a control (for instance a button) should raise validation events when it gains focus.

VB.NET Serial Data Parsing

I’m trying to read a stream of data from serial port coming from a digital scale.
If I send the data stream on a textbox I have a correct visualization (except first line)
Stream in textbox
I would like to catch only one row to use this data.
I have try with following code
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim alol As String
alol = SerialPort1.ReadLine
Label1.Text = alol
End Sub
but what append is that every time I click the button, the label, instead of showing the row value "+0000.26kg", take different section of the data stream (EG: "+00" "KG" "000.2" "+0000.26k" ".26kg" and so on.)
Can anyone suggest to me a way to catch this value ?
The string of interest start always with + or - symbol and end with, I guess, a return.
First thing I would check is the parameters on your SerialPort1 control. Make sure the baud rate in particular is set to a value that is supported by your actual serial port.

How do I make a textbox read only using code when an event happens in VB?

I've made a program in VB where the user selects from a drop down box whether they would like to find out speed, distance or time. There are three textboxes on the form where the user can enter speed, distance and time, and they don't enter anything for the one which they want to find out.
When the user chooses to find out speed, I want the speed textbox to be changed to read only, when the user chooses to find out distance, I want that textbox to be changed to read only, etc.
Thanks in advance.
You can make a Textbox read only by using the following code:
textbox1.ReadOnly = true
You can also found out more here.
Handle the SelectedIndexChanged event and set the Enabled property in there.
Private Sub ComboBox1_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
Me.TextBoxSpeed.Enabled = ComboBox1.SelectedItem <> "Speed"
Me.TextBoxTime.Enabled = ComboBox1.SelectedItem <> "Time"
Me.TextBoxDistance.Enabled = ComboBox1.SelectedItem <> "Distance"
End Sub

Delay textbox-textchanged in vb

I am a simple beginner and need small help:
I have textbox1 and textbox2.
Supposed when you put a number (for ex. 21) in the textbox1, I need textbox2 to give me the double number (42). I mean that I need textbox2.text=2*textbox1.text
I used this simple code :
Private Sub TextBox1_Textlength(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles TextBox1.TextChanged
TextBox2.Text = 2*TextBox1.Text
The problem is: when I wrote (in textbo1) only one digit everything it's ok, but I could not write two (or more) digits.
How do I make a delay (interval) which allows me to type a number like (1990 for example) before firing textbox1_changed?
TextChanged fires every time you change the content of the textbox. So there is no way to block this behavior. Perhaps you could add a button and move the recalculation on the button click event or better add an event handler for the Validating event.
This event is triggered when you exit from the control and you have also the option to check the input and block the exiting from the TextBox control
Private Sub textBox1_Validating(ByVal sender As Object, _
ByVal e As System.ComponentModel.CancelEventArgs) Handles TextBox1.Validating
Dim v as Integer
if Not Int32.TryParse(TextBox1.Text, v) Then
e.Cancel = True
MessageBox.Show("Please type a valid number")
Else
TextBox2.Text = (v * 2).ToString
End If
End Sub
Notice that when you handle the user input expecting a numeric value you should apply particular attention because you don't know what the user types. In this case the Int32.TryParse seems to be the appropriate approach.
Another suggestion is to enable immediately the Option Strict ON in your project, the default is OFF and this allows very dangerous code like treating a string like it was a number.
You don't need to. Just allow the TextChanged event to fire every time, and the second text box will always display twice the value of the first one, so when 1 is entered, it will show 2, when the 9 is added, it will show 38, and so on. You should of course address Steve's concerns about validation, and implied type conversions.

Is there any other way to validate textbox values in VB.net

I am trying to validate textbox values during runtime in vb.net I have following code which is validating txtno from database table tblmachines. But i have problem with chartype and stringtype. Is there any other solution to fix that problem?
Private Sub txtno_KeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles txtno.KeyPress
If e.KeyChar = Microsoft.VisualBasic.ChrW(Keys.Return) Then
e.Handled = True
If (Me.txtno.Text = "") Then
Interaction.MsgBox("!!!!!!!!Machine number can not be empty. Please Correct.!!!!!!!!", &H40, "Check Machine Number")
Me.txtno.Focus()
ElseIf (Me.txtno.Text = "0") Then
Me.txtturnover.Focus()
Else
Dim table As DataTable = Me.DataSet1.Tables.Item("tblmachines")
Dim defaultView As DataView = table.DefaultView
defaultView.RowFilter = ("local_no='" & Me.txtno.Text & "'")
If ((Char.IsLetter(CharType.FromString(Me.txtno.Text)) Or (defaultView.Count = 0)) Or (StringType.StrCmp(Me.txtno.Text, "", False) = 0)) Then
Interaction.MsgBox("This machine is not on database. Please correct machine number.", &H40, "Check Machine Number")
Me.txtno.Focus()
Else
Me.txtturnover.Focus()
End If
End If
End If
I think you'd be better off using validation from the Winforms library than in the KeyPress event. KeyPress is going to cause a lot of validation scripts to be run and will bog down your app.
I think you should do the validation in the following steps
Check to ensure that there is data in the texbox
Validate that the data entered in the textbox is in the proper format. You can use regular code, or possibly a RegEx for that.
Validate that the number entered is a part of the database. I made it a habit reset the filters to a blank string before applying any new filters to the table.
The good part about using inbuilt validation is that you do not have to worry about moving focus around.
The control has a property called CausesValidation - if you set it to true (which it already is) then this control will run the validation code. If you do not want the control to run validation code, you can turn the property to False.
The validation happens as Focus shifts - so when you focus off a control, it's validation events are fired.
The events Validating and Validated are commonly used for this purpose. You can put your code validation in there instead of putting it on the KeyPress.
This is not the proper way to let the user input this specific data. You've got a list of valid entries available from your database. Put them in a ComboBox so the user doesn't have to guess and can't get it wrong.