VB.NET How to avoid first key press when captured it as hotkey? - vb.net

I managed to make my app capture any key to use it as a hotkey, but when I press the key the hotkey function is activated. This is what I have so far:
Private Sub tmrFunc_Tick(sender As Object, e As EventArgs) Handles tmrFunc.Tick
'Function
End Sub
Private Sub tmrKey_Tick(sender As Object, e As EventArgs) Handles tmrKey.Tick
'Uses the hotkey to start and stop tmrF
End Sub
Private Sub lblCapKey_Click(sender As Object, e As EventArgs) Handles lblCapKey.Click
tmrKey.Enabled = False
txtbStartFunc.Enabled = True
txtbStartFunc.Text = "Press any key"
txtbStartFunc.Focus()
End Sub
Private Sub txtbStartFunc_KeyDown(sender As Object, e As KeyEventArgs) Handles txtbStartFunc.KeyDown
If e.KeyCode = Keys.F10 Then
txtbStartFunc.Text = "F10"
End If
tmrKey.Enabled = True
txtbStartFunc.Enabled = False
End Sub
The current code perfectly captures the key and uses it as a hotkey, the problem is that the hotkey is activated on this first key pressed and that causes it to be activated unexpectedly at the wrong time.
My current goal is that the function is not activated with the first keystroke, but is activated with the following keystrokes.
I am expecting something like this:
Private Sub txtbStartFunc_KeyDown(sender As Object, e As KeyEventArgs) Handles txtbStartFunc.KeyDown
If e.KeyCode = Keys.F10 Then
txtbStartFunc.Text = "F10"
End If
tmrKey.Enabled = True
'=========================
tmrFunc.Enabled = False
'=========================
txtbStartFunc.Enabled = False
End Sub

Here's a solution that finally worked for me. It allows you to set the hotkeys between F1 and F10, but won't let you select the same key for both of them.
This is pretty different than what you had, so take your time studying it and ask as many questions as need be:
Public Class Form1
Private Const KeyDownBit As Integer = &H8000
Private Enum HotKeyType
StartClicker
StopClicker
End Enum
Private _StartHotkey As Keys
Private _StopHotKey As Keys
Private SelectingHotKey As HotKeyType
Private HotKeySelected As Boolean = False
Private _SettingHotKey As Boolean = False
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKeys As Integer) As Short
Private Property StartHotKey As Keys
Get
Return _StartHotkey
End Get
Set(value As Keys)
If value <> StopHotKey Then
_StartHotkey = value
TextBox1.Text = StartHotKey.ToString
End If
End Set
End Property
Private Property StopHotKey As Keys
Get
Return _StopHotKey
End Get
Set(value As Keys)
If value <> StartHotKey Then
_StopHotKey = value
TextBox2.Text = StopHotKey.ToString
End If
End Set
End Property
Private Property SettingHotKey As Boolean
Get
Return _SettingHotKey
End Get
Set(value As Boolean)
If value Then
HotKeySelected = False
Timer2.Stop()
Else
Timer2.Start()
End If
_SettingHotKey = value
End Set
End Property
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.KeyPreview = True
Timer1.Enabled = False
Timer2.Enabled = False
Timer1.Interval = 50
Timer2.Interval = 50
TextBox1.ReadOnly = True ' they just stay this way all the time
TextBox2.ReadOnly = True ' they just stay this way all the time
StartHotKey = Keys.F1
StopHotKey = Keys.F2
Timer2.Start()
End Sub
Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
Dim startKeyDown, stopKeyDown As Boolean
GetAsyncKeyState(StartHotKey) ' disregard first call to "flush it"
startKeyDown = (GetAsyncKeyState(StartHotKey) And KeyDownBit) = KeyDownBit ' see if it's down
GetAsyncKeyState(StopHotKey) ' disregard first call to "flush it"
stopKeyDown = (GetAsyncKeyState(StopHotKey) And KeyDownBit) = KeyDownBit ' see if it's down
TextBox1.BackColor = If(startKeyDown, Color.Green, Control.DefaultBackColor)
TextBox2.BackColor = If(stopKeyDown, Color.Green, Control.DefaultBackColor)
If startKeyDown Then
Timer1.Start()
End If
If stopKeyDown Then ' if you hold both down, then it'll stop
Timer1.Stop()
Label1.BackColor = Control.DefaultBackColor
End If
End Sub
Private Sub BothButtons_Click(sender As Object, e As EventArgs) Handles Button1.Click, Button2.Click
SelectingHotKey = If(sender Is Button1, HotKeyType.StartClicker, HotKeyType.StopClicker)
SettingHotKey = True ' automatically turns off Timer2
Dim tb As TextBox = If(sender Is Button1, TextBox1, TextBox2)
tb.Text = "Press F1 to F10"
End Sub
Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean
Select Case keyData
Case Keys.F1 To Keys.F10
If SettingHotKey Then
If SelectingHotKey = HotKeyType.StartClicker Then
If keyData <> StopHotKey Then
StartHotKey = keyData
HotKeySelected = True
Return True
End If
Else
If keyData <> StartHotKey Then
StopHotKey = keyData
HotKeySelected = True
Return True
End If
End If
End If
End Select
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
Private Sub Form1_KeyUp(sender As Object, e As KeyEventArgs) Handles Me.KeyUp
If SettingHotKey AndAlso HotKeySelected Then
SettingHotKey = False ' restarts Timer2 once selected key has been released
End If
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Label1.BackColor = Color.Green
Label1.Text = DateTime.Now.ToString("HH:mm:ss.ffff") ' just to show it's "clicking"
End Sub
End Class

Okay, here's a little example of my program, which shows my problem.
This is the interface:
enter image description here
When I press F1, the counter starts to add 1 to itself, when I press F2, the counter stops. The Select button changes F1 to F9 or F2 to F10, but when I change the key the function is triggered, that is, if the counter is stopped, and the key is at F1, when I click Select to change from F1 to F9, the counter is activated.
Here is an example of the code, so you can see the problem first hand:
Public Class Form1
Declare Function GetAsyncKeyState Lib "user32" (ByVal vKeys As Integer) As Short
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Label1.Text += 1
End Sub
Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
Dim a, b As Boolean
If TextBox1.Text = "F1" Then
a = GetAsyncKeyState(Keys.F1)
ElseIf TextBox1.Text = "F9" Then
a = GetAsyncKeyState(Keys.F9)
End If
If TextBox2.Text = "F2" Then
b = GetAsyncKeyState(Keys.F2)
ElseIf TextBox2.Text = "F10" Then
b = GetAsyncKeyState(Keys.F10)
End If
If a = True Then
Timer1.Start()
ElseIf b = True Then
Timer1.Stop()
End If
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Timer2.Enabled = False
TextBox1.ReadOnly = False
TextBox1.Text = "Press any key"
TextBox1.Focus()
End Sub
Private Sub TextBox1_KeyDown(sender As Object, e As KeyEventArgs) Handles TextBox1.KeyDown
e.SuppressKeyPress = True
If TextBox1.ReadOnly = False Then
If e.KeyCode = Keys.F9 Then
TextBox1.Text = "F9"
Else
TextBox1.Text = "F1"
End If
End If
Timer2.Enabled = True
TextBox1.ReadOnly = True
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Timer2.Enabled = False
TextBox2.ReadOnly = False
TextBox2.Text = "Press any key"
TextBox2.Focus()
End Sub
Private Sub TextBox2_KeyDown(sender As Object, e As KeyEventArgs) Handles TextBox2.KeyDown
e.SuppressKeyPress = True
If TextBox2.ReadOnly = False Then
If e.KeyCode = Keys.F10 Then
TextBox2.Text = "F10"
Else
TextBox2.Text = "F2"
End If
End If
Timer2.Enabled = True
TextBox2.ReadOnly = True
End Sub
End Class
#Idle_Mind

Related

How to subtract checkbox values?

When I select a checkbox, the value gets added in the textbox and gets incremented when I check another. Problem is, when I uncheck them, it should subtract the values too. Total_sum in my textbox. Please help me.
Dim sum As Integer
Public Sub ChangeValue(add As Boolean, value As Decimal)
sum += If(add, value, -value)
Total_sum.Text = sum.ToString
End Sub
Private Sub chk_1_CheckedChanged(sender As Object, e As EventArgs) Handles chk_1.CheckedChanged
If chk_1.Checked = True Then
ChangeValue(DirectCast(sender, CheckBox).Checked = True, 25I)
End If
End Sub
Private Sub chk_2_CheckedChanged(sender As Object, e As EventArgs) Handles chk_2.CheckedChanged
If chk_2.Checked = True Then
ChangeValue(DirectCast(sender, CheckBox).Checked, 25I)
End If
End Sub
Private Sub chk_3_1_CheckedChanged(sender As Object, e As EventArgs) Handles chk_3_1.CheckedChanged
If chk_3_1.Checked = True Then
chk_3_2.Checked = False
ChangeValue(DirectCast(sender, CheckBox).Checked, 15I)
End If
End Sub
Private Sub chk_3_2_CheckedChanged(sender As Object, e As EventArgs) Handles chk_3_2.CheckedChanged
If chk_3_2.Checked = True Then
chk_3_1.Checked = False
ChangeValue(DirectCast(sender, CheckBox).Checked, 30I)
End If
End Sub
Private Sub chk_4_CheckedChanged(sender As Object, e As EventArgs) Handles chk_4.CheckedChanged
If chk_4.Checked = True Then
ChangeValue(DirectCast(sender, CheckBox).Checked, 20D)
End If
End Sub
Private Sub chk_5_1_CheckedChanged(sender As Object, e As EventArgs) Handles chk_5_1.CheckedChanged
If chk_5_1.Checked = True Then
chk_5_2.Checked = False
chk_5_3.Checked = False
ChangeValue(DirectCast(sender, CheckBox).Checked, 0D)
End If
End Sub
Private Sub chk_5_2_CheckedChanged(sender As Object, e As EventArgs) Handles chk_5_2.CheckedChanged
If chk_5_2.Checked = True Then
chk_5_1.Checked = False
chk_5_3.Checked = False
ChangeValue(DirectCast(sender, CheckBox).Checked, 15D)
End If
End Sub
You do not need the DirectCast. You know what the sender is. Just passing the Boolean chk_1.Checked to ChangeValue will either increment or decrement the sum.
Private sum As Integer
Public Sub ChangeValue(add As Boolean, value As Integer)
sum += If(add, value, -value)
Total_sum.Text = sum.ToString
End Sub
Private Sub chk_1_CheckedChanged(sender As Object, e As EventArgs) Handles chk_1.CheckedChanged
ChangeValue(chk_1.Checked, 25)
End Sub

Return the currently selected object

The code says everything, if I press F1 and I'm already with Button1 selected, then it should select Button2 and vice-versa.
If keyData = Keys.F1 Then
If Button1.Select() = True Then
Button2.Select()
ElseIf Button2.Select() = True Then
Button1.Select()
Else
Button1.Select()
End If
End If
But the expression "Button2.Select() = True" doesn't return a value.
Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
If e.KeyValue = Keys.F1 Then
If ActiveControl.Name = "Button1" Then
Button2.Select()
Else
Button1.Select()
End If
End If
End Sub
Actually, F1 is a poor choice because it is traditionally the "Help" key.
We can use form keydown (set form keypreview property to true) or use button previewkeydown like these:
Private Sub Button1_PreviewKeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.PreviewKeyDownEventArgs) Handles Button1.PreviewKeyDown
If e.KeyCode = Keys.F1 Then
Button2.Focus()
End If
End Sub
Private Sub Button2_PreviewKeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.PreviewKeyDownEventArgs) Handles Button2.PreviewKeyDown
If e.KeyCode = Keys.F1 Then
Button1.Focus()
End If
End Sub

VB.NET Windows Forms - Temporarily Disable Close 'X' Button

I have a form that prompts a user for confirmation before running a BackgroundWorker that performs some calculations. Those calculations can take anywhere from 10-30 seconds to run and I want to make sure that once the calculations begin running, they are allowed to finish uninterrupted.
Is there a way to temporarily disable the Close Button in the title bar until the BackgroundWorker finishes its job?
I found a couple similar questions but they look like a more permanent solution (here and here). I'd like the Close Button to be disabled only temporarily while the BackgroundWorker does its job.
Any help would be much appreciated. Thanks!
Private ImBusy As Boolean = False
Private Sub LookBusyForTheBoss()
Me.UseWaitCursor = True
Me.Cursor = Cursors.WaitCursor
Me.Enabled = False
ProgressBar1.UseWaitCursor = False
ProgressBar1.Style = ProgressBarStyle.Marquee
ImBusy = True
End Sub
Private Sub Form77_FormClosing(...) Handles Me.FormClosing
If ImBusy Then e.Cancel = True
End Sub
Private Sub OkHeIsGone()
Me.UseWaitCursor = False
Me.Cursor = Cursors.Default
Me.Enabled = True
ImBusy = False
End Sub
Disabling the close button would be bad taste in the extreme. Fix your application so that the calculation can be interrupted.
I agree with not hiding the 'X' but if you want it really bad I think this over here is what you are looking for:
Disable Close Button in Vb.Net
Something along these lines might work:
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
doNotClose = True
Do
'
'etc
'
'simulate long running
For x As Integer = 1 To 1000
Threading.Thread.Sleep(10)
Next
Exit Do
Loop
doNotClose = False
If closerequested Then
Me.BeginInvoke(Sub()
Me.Close()
End Sub)
End If
End Sub
Dim doNotClose As Boolean = False
Dim closerequested As Boolean = False
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
closerequested = True
If doNotClose Then
e.Cancel = True
Exit Sub
End If
End Sub
or this
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
doNotClose = True
Do
'
'etc
'
'simulate long running
For x As Integer = 1 To 1000
Threading.Thread.Sleep(10)
Next
Exit Do
Loop
doNotClose = False
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
If closerequested Then
Me.Close()
End If
End Sub
Dim doNotClose As Boolean = False
Dim closerequested As Boolean = False
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
closerequested = True
If doNotClose Then
e.Cancel = True
Exit Sub
End If
End Sub

VB.net stopping a backgroundworker

I want to create a button that could stop my background worker and end all the process it is working on.
Here is my sample backgroundworker code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
If BackgroundWorker1.IsBusy <> True Then
BackgroundWorker1.RunWorkerAsync()
End If
Catch ex As Exception
End Try
End Sub
Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim counter As Integer = 1
Do
'updated code with stop function----------------
BackgroundWorker1.WorkerSupportsCancellation = True
If BackgroundWorker1.CancellationPending Then
e.Cancel = True
ProgressBar1.Value = 0
Exit Do
End If
'updated code with stop function----------------
ListBox1.Items.Add(counter)
ProgressBar1.Value = ((counter - 1) / limit) * 100
counter = counter + 1
Loop While(counter <= 999999999999999999)
End Sub
Private Sub BackgroundWorker1_ProgressChanged(sender As System.Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
Try
Catch ex As Exception
End Try
End Sub
Private Sub BackgroundWorker1_Completed(sender As System.Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
Try
Catch ex As Exception
End Try
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = False
End Sub
'updated code with stop function----------------
Private Sub StopButton_Click(sender As Object, e As EventArgs) Handles StopButton.Click
If BackgroundWorker1.IsBusy Then
If BackgroundWorker1.WorkerSupportsCancellation Then
BackgroundWorker1.CancelAsync()
End If
End If
End Sub
'updated code with stop function----------------
I want to reset the loop and return the Progress Bar to 0% when i stop the backgroundworker.
Is this possible?
The code above has been updated and it is now working fine.
I have added this code inside my do loop:
BackgroundWorker1.WorkerSupportsCancellation = True
If BackgroundWorker1.CancellationPending Then
e.Cancel = True
ProgressBar1.Value = 0
Exit Do
End If
I created a button that stops the worker:
Private Sub StopButton_Click(sender As Object, e As EventArgs) Handles StopButton.Click
If BackgroundWorker1.IsBusy Then
If BackgroundWorker1.WorkerSupportsCancellation Then
BackgroundWorker1.CancelAsync()
End If
End If
End Sub
The Backgroundworker class has the method CancelAsync() which you need to call to cancel the execution of the bgw.
You need to set the Backgroundworker.WorkerSupportsCancellation property to true and inside the while loop you need to check the CancellationPending property wether the value is true which indicates a call to the CancelAsync() method.
If CancellationPending evaluates to true, you would ( which you should have done already ) call one of the overloaded ReportProgress() (Docu) methods to set your ProgressBar value to the desired value.
EDIT: You should set the Cancel property of the DoWorkEventArgs to true so you can check the Cancelled property of the RunWorkerCompletedEventArgs inside the RunworkerCompletedevent.
You also shouldn not access any controls which lives in the UI thread. You better use the ProgressChanged(Docu) event.
See: BackgroundWorker Docu
Public Class Form1
Private iVal As Integer = 0
Private Sub bgw_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgw.DoWork
For iVal = iVal To 100 Step 1
bgw.ReportProgress(iVal)
Threading.Thread.Sleep(99)
If (bgw.CancellationPending = True) Then
e.Cancel = True
Exit For
End If
Next
End Sub
Private Sub bgw_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bgw.ProgressChanged
pbar.Value = e.ProgressPercentage
lblProgrss.Text = e.ProgressPercentage.ToString() & "%"
End Sub
Private Sub bgw_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bgw.RunWorkerCompleted
If (e.Cancelled = True) Then
pic.Visible = False
pbar.Value = iVal
lblProgrss.Text = iVal & "%"
btnstart.Text = "Start"
btnstart.BackColor = Color.Green
Else
pic.Visible = False
btnstart.Text = "Start"
btnstart.BackColor = Color.Green
iVal = 0
End If
End Sub
Private Sub btnstart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnstart.Click
If (btnstart.Text = "Start") Then
btnstart.Text = "Stop"
btnstart.BackColor = Color.Red
pic.Visible = True
bgw.RunWorkerAsync()
Else
If (bgw.IsBusy = True) Then
btnstart.Text = "Start"
btnstart.BackColor = Color.Green
bgw.CancelAsync()
End If
End If
End Sub
End Class

Disable Button until multiple Textboxes got Validated

I have a form with over 10 textboxes and 1 button, I would like to disable the button with a realtime validation until all textboxes filled with a 10 or a 13 length numeric value, my code is the following so far:
Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
For Each userID As Control In Me.Controls.OfType(Of TextBox)()
AddHandler userID.TextChanged, AddressOf ValidateAllFields
Next userID
End Sub
Private Sub userID_KeyPress(ByVal sender As Object, ByVal e As KeyPressEventArgs) Handles Me.KeyPress
If e.KeyChar <> ChrW(Keys.Back) Then
If Char.IsNumber(e.KeyChar) Then
Else
e.Handled = True
End If
End If
End Sub
Private Function ValidateAllFields()
Dim Validation As Boolean = True
For Each userID As Control In Me.Controls.OfType(Of TextBox)()
Dim e As New System.ComponentModel.CancelEventArgs
e.Cancel = False
Call userID_Validating(userID, e)
If e.Cancel = True Then Validation = False
Next userID
buttonSave.Enabled = Not Me.Controls.OfType(Of TextBox).Any(Function(userID) userID.Text.Length <> 10 AndAlso userID.Text.Length <> 13)
Return Validation
End Function
Private Sub userID_Validating(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles _
user00.Validating, _
user01.Validating, _
user02.Validating, _
user03.Validating, _
user04.Validating, _
user05.Validating, _
user06.Validating, _
user07.Validating, _
user07.Validating, _
user08.Validating, _
user09.Validating, _
user10.Validating, _
user11.Validating
If Not IsNumeric(sender.Text) OrElse (sender.Text.Length <> 10) AndAlso (sender.Text.Length <> 13) Then
ErrorProvider1.SetError(sender, "")
ErrorProvider2.SetError(sender, "Please enter a valid User ID.")
e.Cancel = True
Else
ErrorProvider1.SetError(sender, "Valid User ID.")
ErrorProvider2.SetError(sender, "")
End If
End Sub
Thanks to your help it works as I wanted, but can you help me improve/clean it? I'm still studying vb, I'm open to any suggestion. Thanks in advance!
Here you have a code performing the actions you want:
Dim done1, done2, done3 As Boolean
Dim targetLength1 As Integer = 10
Dim targetLength2 As Integer = 13
Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
Try
If (IsNumeric(TextBox1.Text)) Then
If (TextBox1.Text.Length = targetLength1 Or TextBox1.Text.Length = targetLength2) Then
done1 = True
End If
End If
If (done1 And done2 And done3) Then
Button1.Enabled = True
End If
Catch ex As Exception
End Try
End Sub
Private Sub TextBox2_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox2.TextChanged
Try
If (IsNumeric(TextBox2.Text)) Then
If (TextBox2.Text.Length = targetLength1 Or TextBox2.Text.Length = targetLength2) Then
done2 = True
End If
End If
If (done1 And done2 And done3) Then
Button1.Enabled = True
End If
Catch ex As Exception
End Try
End Sub
Private Sub TextBox3_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox3.TextChanged
Try
If (IsNumeric(TextBox3.Text)) Then
If (TextBox3.Text.Length = targetLength1 Or TextBox3.Text.Length = targetLength2) Then
done3 = True
End If
End If
If (done1 And done2 And done3) Then
Button1.Enabled = True
End If
Catch ex As Exception
End Try
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Button1.Enabled = False
End Sub
It accounts just for 3 textboxes (TextBox1, TextBox2 and TextBox3) and 1 button (Button1) but you can extend the idea to as many textboxes as you wish. It relies on the TextChanged even of each textbox. When the condition is met (given textbox has a number whose length is 10 or 13), the corresponding flag is set to true (e.g., done1 for TextBox1...). When all the flags are true (all the textboxes contain the expected information), the button is disabled.
I think would better to use TextChanged Event ..
Private Sub TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged, TextBox2.TextChanged, ....., TextBox10.TextChanged
Chk4ButtonEnabled()
End Sub
Sub Chk4ButtonEnabled()
Dim s as String
For Each userID As Control In Me.Controls
If userID.GetType Is GetType(TextBox) Then
s = userID.Text
If Not s.Length = 10 OR Not s.Length = 13 Then
ErrorProvider1.SetError(userID, "")
buttonSave.Enabled = False
Else
ErrorProvider1.SetError(userID, "Valid User ID.")
buttonSave.Enabled = True
End If
End If
Next
End Sub