Delay textbox-textchanged in vb - vb.net

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.

Related

Textbox search accented characters problem?

I am looking for information on datagrid using textbox assign textchanged_event.
The problem I encountered was that when I typed the characters with a accented then datagrid would blink (it seems every change would be recorded in the textbox not just the final result).
Example: when typing "khang"
If I continue to type the letter "a", in english it will result in "khanga" and everything goes well, but in some languages it should be "khâng" and I see in textchanged it will take many steps as:
"khang" -> "khang•" -> "khang" -> "khan" -> "kha" -> "khâ" ->"khân"->"khâng"
in this moment, the datagrid will blink continuously.
what should I do to textchanged only handle the final result?
Thanks for advices!
You can't guarantee that you only handle the final value unless you use a Button.Click instead of a TextBox.TextChanged, or maybe force the user to hit Enter and handle the TextBox.KeyDown or the like. What you can do instead is ensure that you only act on the TextChanged if no other TextChanged has occurred for a specific length of time by using a Timer. That way, the delay is not so great that the user really feels it but it is long enough to allow multiple keystrokes without acting on them in between.
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
'Start/restart the Timer every time the Text changes.
Timer1.Stop()
Timer1.Start()
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
'Perform filter when time expires.
Timer1.Stop()
BindingSource1.Filter = $"SomeColumn LIKE '%{TextBox1.Text}%'"
End Sub
It's up to you want you set the Interval of the Timer to but I'd be looking at around 300. You can do a bit of experimentation to find what gives you the best balance.

Visual Basic Detect Mouse Position

So i want to make a maze game in Visual Basic and if the cursor reaches a certain panel, it will show a message box ONCE and then the Form closes.
The question is How?
I've tried
Private Sub Panel1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Panel1.Paint
If Cursor.Position = Panel1 Then
MsgBox("Completed")
Application.Exit()
End If
End Sub
And didn't work. I got
Error 1 Overload resolution failed because no accessible '=' can be
called with these arguments:
'Public Shared Operator =(left As System.Drawing.Point, right As System.Drawing.Point) As Boolean': Value of type
'System.Windows.Forms.Panel' cannot be converted to
'System.Drawing.Point'. C:\Documents and Settings\Admin\Local
Settings\Application Data\Temporary
Projects\WindowsApplication1\Form1.vb 4 12 WindowsApplication1
Remember that i want the message box to only appear once, because sometimes when the cursor is on the panel, it shows multiple msgbox until the cursor is outta there.
I want the mouse inside the panel and run a code.
I believe there is an event called 'mouse enter' event you can use so if you type the code for the messagebox in that even for the control you want them to mouseover it will pop up everytime they do that.
For it to to nly pop up once make a counter that adds 1 and dont execute that code if the counter is already on 1.
I had a little search and found: Determine whether the mouse is over a control? (over a Control pixel range)
I just knocked up a test with a button and seemed to work fine. Please adapt to your own needs.
Private Sub Button1_Paint(sender As Object, e As PaintEventArgs) Handles Button1.Paint
Debug.WriteLine(MouseIsOverControl(Button1))
End Sub
Public Function MouseIsOverControl(ByVal c As Control) As Boolean
Return c.ClientRectangle.Contains(c.PointToClient(Control.MousePosition))
End Function
In this example I've just output "true or false" to determine detection. You can test and change it to your own needs to determine what you want to do depending on 'true/false'. Hope this helps.

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

How to retain contents of datagrid view when applying multiple filters

I am trying to provide my users a nice search capability. I want to do so using textboxes to filter a datagridview. I have a dgv containing all animals in the database. For simplicity sake let’s say the first two columns are animalName and animal (dog or cat). I have two textboxes used for filtering, one for each of those two columns. Let's say I want to find all dogs named Buddy. In my first text box I type 'Buddy' and, because of the filter code behind the textbox change event the dgv now contains only the Buddys. When I go to textboxAnimal and type 'd' for dog the dgv changes to show all the dogs; not just the ones named Buddy. How can I make it such that the results of the first filter stay in place when I apply the second filter?
I assume I need to use the lostFocus (or gotFocus or leave) event of the first textbox but just don’t know what code to put behind it. I guess I could hard code a select statement that would then be used to repopulate the datagridview but this could get onerous as I’m going to have many textboxes; not just two.
Any help would be greatly appreciated.
Focus is irrelevant. You handle the TextChanged event of both TextBox controls and you build the filter from scratch every time, taking both fields into account, e.g.
Private Sub TextBoxes_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged,
TextBox2.TextChanged
Me.BindingSource1.Filter = String.Format("Column1 LIKE '%{0}%' AND Column2 LIKE '%{1}%'",
TextBox1.Text,
TextBox2.Text)
End Sub
One pitfall of filtering on TextChanged, regardless of how many fields you're filtering on, is that you will end up filtering needlessly several times when the user types several letters. For instance, if the user intends to type "bud" then there's no point to filtering after the "b" and the "bu" and it may actually degrade performance if the data set is large. For that reason, it's nice to use a Timer to delay filtering for a short period. That will defer filtering until the user stops typing in most cases. You can play with the Interval to get the performance you want. Probably about 500 ms should do it but it's up to you.
Private Sub TextBoxes_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged,
TextBox2.TextChanged
'Start or restart the timer because the user typed something.
Me.Timer1.Stop()
Me.Timer1.Start()
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
'The timer has expired so the user has not typed anything for the prescribed amount of time.
Me.BindingSource1.Filter = String.Format("Column1 LIKE '%{0}%' AND Column2 LIKE '%{1}%'",
TextBox1.Text,
TextBox2.Text)
End Sub

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

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.