Visual Indication of Focus and Adding Click Event To all TextBoxes - vb.net

I'm working on a program wherein I have around 400 Text Boxes and I need to program an effect to make them show that they have focus. I can get the visual part down (Unless someone knows how to add a soft blue outline to a text box in VB), but I'm having trouble with creating GotFocus and LostFocus events that handle all of my Text Boxes at once. I've tried
Dim txtBox = Me.Controls.OfType(Of TextBox)
Private Sub TextBox_GotFocus(sender As Object, e As EventArgs) Handles txtBox.GotFocus
But I get a "Must have WithEvents variable" error which I don't quite understand how to fix. I've tried
Public Sub txtBoxGotFocusHandler(ByVal sender As Object,
ByVal e As System.EventArgs)
For Each txtBox As TextBox In Me.Controls 'References all text boxes in form
If txtBox.Focus = True Then
txtBox.BackColor = Color.Black
End If
Next
And I've tried a few other somewhat related things I've seen around the internet, but to no avail. Any help would be appreciated

You can make your app at runtime with any controls. You could query the layout of your app from SQL and from a simple change your app layout changes.
Private FocusRectangle As System.Drawing.Graphics
Private OldRectangle As System.Drawing.Graphics
Private MyTextBoxes As New List(Of TextBox)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
MyTextBoxes.Clear()
For xcount = 0 To 399
MyTextBoxes.Add(New TextBox)
With MyTextBoxes.Item(xcount)
.Name = "MyTextBoxes" & (xcount + 1).ToString
.Text = ""
.Location = New Point(0, 0)
.Size = New Size(50, 13)
.Visible = True
AddHandler .GotFocus, AddressOf MyTextBoxes_GotFocus
AddHandler .LostFocus, AddressOf MyTextBoxes_LostFocus
End With
Me.Controls.Add(MyTextBoxes.Item(xcount))
'add them to a panel....
'Panel1.Controls.add(MyTextBoxes.Item(xcount))
Next
End Sub
Sub MyTextBoxes_GotFocus(sender As Object, e As EventArgs)
Dim ThisTextBox As TextBox = DirectCast(sender, TextBox)
Dim xPen As New System.Drawing.Pen(Color.LightBlue)
FocusRectangle = Me.CreateGraphics()
FocusRectangle.DrawRectangle(xPen, ThisTextBox.Location.X - 1, ThisTextBox.Location.Y - 1, ThisTextBox.Size.Width + 1, ThisTextBox.Size.Height + 1)
OldRectangle = FocusRectangle
End Sub
Sub MyTextBoxes_LostFocus(sender As Object, e As EventArgs)
Dim ThisTextBox As TextBox = DirectCast(sender, TextBox)
OldRectangle.Dispose()
End Sub
Private Sub Form1_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
MyTextBoxes.Item(0).Focus()
End Sub

If you created your form with the Designer, the WithEvents is added for you automatically.
If you are declaring 400 text boxes as Private fields, you would declare them as Private WitheEvents txtBox As TextBox
If you're creating the text boxes programatically and adding them to a collection of textboxes or something, then you can't do WithEvents.
But all WithEvents does is allow you to add Handeles TextBox.SomeEvent to a function. Instead you can do this:
Dim txtBox As New TextBox
...
AddHandler txtBox.GotFocus, AddressOf txtBoxGotFocusHandler
Me.Controls.Add(txtBox)

Related

VB fires changetext event before control is loaded

I need to add some controls to a Visual Basic 2017 form programmatically. One of the controls is a textbox that needs a changetext event handler. Below is some code that accomplishes that task.
HOWEVER, the changetext event handler seems to fire right away, before the form even loads... before the textbox itself even loads! A "click" handler works fine, as expected. But changetext? Nope.
I've thrown together a simplified version to demonstrate. The line with the "DIES RIGHT HERE" comment causes the problem (not the comment, but the code to the left of it).
A textbox that is added at design time will work fine, not cause this problem, but that isn't an option.
What's causing this the changetext handler to be run early? How do I work around this?
Public Class Form1
Dim txtTest As TextBox
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim pntTextBox As Point
pntTextBox.X = 100
pntTextBox.Y = 100
txtTest = New TextBox
With txtTest
.Location = pntTextBox
.Width = 100
AddHandler txtTest.TextChanged, AddressOf txtTest_TextChanged
End With
Me.Controls.Add(txtTest)
End Sub
Private Sub txtTest_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyClass.TextChanged
Dim strTest As String
strTest = Str(txtTest.Width) ' ****** DIES RIGHT HERE
MsgBox(strTest)
End Sub
End Class
Made a few changes. Works.
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For x As Integer = 1 To 2 'create multiple TB's
Dim pntTextBox As Point
pntTextBox.X = 100 * x
pntTextBox.Y = 100
Dim txtTest As TextBox = New TextBox
With txtTest
txtTest.Name = "tb_" & x.ToString
AddHandler txtTest.TextChanged, AddressOf txtTest_TextChanged
.Location = pntTextBox
.Width = 100
End With
Me.Controls.Add(txtTest)
Next
End Sub
Private Sub txtTest_TextChanged(ByVal sender As Object,
ByVal e As System.EventArgs) 'no handler at design time
Dim tb As TextBox = DirectCast(sender, TextBox)
Dim strTest As String
strTest = tb.TextLength.ToString
Debug.WriteLine("{0} {1}", tb.Name, strTest) 'put breakpoint here
End Sub
End Class

Detect multiple control changed in VB.Net

how can I control some controls that will be created automatically during the execution of the application?
My add control
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim NewCheckbox As CheckBox
For i As Integer = 2 To 14
NewCheckbox = New CheckBox
NewCheckbox.Size = New Drawing.Size(15, 14)
NewCheckbox.Location = New Point(98, 40)
NewCheckbox.Name = "cbcard" & i
Me.Controls.Add(NewCheckbox)
next
My checkbox control add, I gave an example to create a checkbox control, but it should be valid for any form of control, be it textbox or button.
how can i detect these controls that are not created but will be created during execution?
checkbox name will be cbcard1, cbcard2, cbcard3 up to 14.
but I want this to be in the form of a handler, or it should probably work with a timer.
Private Sub Checkbox_Changed(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Checkbox.Changed
If Checkbox.checked = true
MsgBox("")
End If
End Sub
You can subscribe to the event using the AddHandler syntax.
For i As Integer = 2 To 14
NewCheckbox = New CheckBox
NewCheckbox.Size = New Drawing.Size(15, 14)
NewCheckbox.Location = New Point(98, 40)
NewCheckbox.Name = "cbcard" & i
Me.Controls.Add(NewCheckbox)
'subscribe to the CheckChanged event (as an example)
AddHandler NewCheckbox.CheckChanged, AddressOf Checkbox_Changed
Next
'all dynamically created checkboxes were subscribed to this event
Private Sub Checkbox_Changed(ByVal sender As System.Object, ByVal e As System.EventArgs)
'sender is the specific checkbox that was changed out of all subscribed checkboxes
Dim checkBox = DirectCast(sender, CheckBox)
If checkbox.checked = true Then MsgBox(checkBox.Name)
End Sub

Detect if a combobox is clicked without using SelectedIndexChange

I would like to ask if it is possible for VB.net applications to detect if a combobox has been changed without using SelectedIndexChange.
For Example my application has 4 comboboxes and this comboboxes was dynamically created from the user configuration. (the tool autocreates the comboboxes when the application was launched). Then once the application was launched, I want to run a SUB everytime those comboboxes was changed. Badly needed help. TIA
If you are creating controls dynamically, you should add the event handlers dynamically as well. There is nothing wrong with using the SelectedIndexChanged event.
You can test this by making a new project and pasting this code inside Public Class Form1.
Private myComboBox1 As ComboBox
Private myComboBox2 As ComboBox
Private Shared selectedIndexChanged As EventHandler =
Sub(sender As Object, e As EventArgs)
Dim myComboBox = DirectCast(sender, ComboBox)
' alert the user as to what was selected
MessageBox.Show(String.Format("{0} value: {1}, index: {2}",
myComboBox.Name, myComboBox.Text, myComboBox.SelectedIndex))
' you can do something different on each one by name in a case statement
Select Case myComboBox.Name
Case "myComboBox1"
' do something for 1
Case "myComboBox2"
' do something for 2
End Select
End Sub
Private Sub addHandlers()
AddHandler myComboBox1.SelectedIndexChanged, selectedIndexChanged
AddHandler myComboBox2.SelectedIndexChanged, selectedIndexChanged
End Sub
Private Sub removeHandlers()
RemoveHandler myComboBox1.SelectedIndexChanged, selectedIndexChanged
RemoveHandler myComboBox2.SelectedIndexChanged, selectedIndexChanged
End Sub
Form eventhandlers
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' dynamically generate combo boxes
myComboBox1 = New ComboBox() With {.Name = "myComboBox1",
.Left = 30,
.Top = 30}
myComboBox2 = New ComboBox() With {.Name = "myComboBox2",
.Left = 30,
.Top = 60}
' add some items
myComboBox1.Items.AddRange({1, 2, 3})
myComboBox2.Items.AddRange({"four", "five", "six"})
' add the combo boxes to the form
Me.Controls.Add(myComboBox1)
Me.Controls.Add(myComboBox2)
' add event handlers
addHandlers()
End Sub
Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
removeHandlers()
End Sub

How to programmatically add controls to a form in VB.NET

I am working on an inventory in Visual Basic 2010 Express Edition. I don't know the number of fields that will be necessary for the inventory. My hope was that I could add textboxes/checkboxes/buttons using for loops in the program. Is there a way to add controls to a form without using the toolbox?
Can I add controls by instantiating them in the program?
Yes.
Private Sub MyForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim MyTextbox as New Textbox
With MyTextbox
.Size = New Size(100,20)
.Location = New Point(20,20)
End With
AddHandler MyTextbox.TextChanged, AddressOf MyTextbox_Changed
Me.Controls.Add(MyTextbox)
'Without a help environment for an intelli sense substitution
'the address name and the methods name
'cannot be wrote in exchange for each other.
'Until an equality operation is prior for an exchange i have to work
'on an as is base substituted.
End Sub
Friend Sub MyTextbox_Changed(sender as Object, e as EventArgs)
'Write code here.
End Sub
Dim numberOfButtons As Integer
Dim buttons() as Button
Private Sub MyForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Redim buttons(numberOfbuttons)
for counter as integer = 0 to numberOfbuttons
With buttons(counter)
.Size = (10, 10)
.Visible = False
.Location = (55, 33 + counter*13)
.Text = "Button "+(counter+1).ToString ' or some name from an array you pass from main
'any other property
End With
'
next
End Sub
If you want to check which of the textboxes have information, or which radio button was clicked, you can iterate through a loop in an OK button.
If you want to be able to click individual array items and have them respond to events, add in the Form_load loop the following:
AddHandler buttons(counter).Clicked AddressOf All_Buttons_Clicked
then create
Private Sub All_Buttons_Clicked(ByVal sender As System.Object, ByVal e As System.EventArgs)
'some code here, can check to see which checkbox was changed, which button was clicked, by number or text
End Sub
when you call: objectYouCall.numberOfButtons = initial_value_from_main_program
response_yes_or_no_or_other = objectYouCall.ShowDialog()
For radio buttons, textboxes, same story, different ending.
Public Class Form1
Private boxes(5) As TextBox
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim newbox As TextBox
For i As Integer = 1 To 5 'Create a new textbox and set its properties26.27.
newbox = New TextBox
newbox.Size = New Drawing.Size(100, 20)
newbox.Location = New Point(10, 10 + 25 * (i - 1))
newbox.Name = "TextBox" & i
newbox.Text = newbox.Name 'Connect it to a handler, save a reference to the array & add it to the form control.
AddHandler newbox.TextChanged, AddressOf TextBox_TextChanged
boxes(i) = newbox
Me.Controls.Add(newbox)
Next
End Sub
Private Sub TextBox_TextChanged(sender As System.Object, e As System.EventArgs)
'When you modify the contents of any textbox, the name of that textbox
'and its current contents will be displayed in the title bar
Dim box As TextBox = DirectCast(sender, TextBox)
Me.Text = box.Name & ": " & box.Text
End Sub
End Class
To add controls dynamically to the form, do the following code. Here we are creating textbox controls to add dynamically.
Public Class Form1
Private m_TextBoxes() As TextBox = {}
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
' Get the index for the new control.
Dim i As Integer = m_TextBoxes.Length
' Make room.
ReDim Preserve m_TextBoxes(i)
' Create and initialize the control.
m_TextBoxes(i) = New TextBox
With m_TextBoxes(i)
.Name = "TextBox" & i.ToString()
If m_TextBoxes.Length < 2 Then
' Position the first one.
.SetBounds(8, 8, 100, 20)
Else
' Position subsequent controls.
.Left = m_TextBoxes(i - 1).Left
.Top = m_TextBoxes(i - 1).Top + m_TextBoxes(i - _
1).Height + 4
.Size = m_TextBoxes(i - 1).Size
End If
' Save the control's index in the Tag property.
' (Or you can get this from the Name.)
.Tag = i
End With
' Give the control an event handler.
AddHandler m_TextBoxes(i).TextChanged, AddressOf TextBox_TextChanged
' Add the control to the form.
Me.Controls.Add(m_TextBoxes(i))
End Sub
'When you enter text in one of the TextBoxes, the TextBox_TextChanged event
'handler displays the control's name and its current text.
Private Sub TextBox_TextChanged(ByVal sender As _
System.Object, ByVal e As System.EventArgs)
' Display the current text.
Dim txt As TextBox = DirectCast(sender, TextBox)
Debug.WriteLine(txt.Name & ": [" & txt.Text & "]")
End Sub
End Class
You can get your Button1 location and than increase the Y value every time you click on it.
Public Class Form1
Dim BtnCoordinate As Point
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim btn As Button = New Button
BtnCoordinate.Y += Button1.Location.Y + 4
With btn
.Location = New Point(BtnCoordinate)
.Text = TextBox1.Text
.ForeColor = Color.Black
End With
Me.Controls.Add(btn)
Me.StartPosition = FormStartPosition.CenterScreen
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Button1Coordinate = Button1.Location
End Sub
End Class

Control array in VB.NET

How do I make a control array for buttons in VB.NET? Like in Visual Basic 6.0...
Is it possible that the syntax can be like the following?
dim a as button
for each a as button in myForm
a.text = "hello"
next
Controls in .NET are just normal objects so you can freely put them into normal arrays or lists. The special VB6 construct of control arrays is no longer necessary.
So you can for example say,
Dim buttons As Button() = { Button1, Button2, … }
For Each button As Button In Buttons
button.Text = "foo"
End For
Alternatively, you can directly iterate over the controls inside a container (e.g. a form):
For Each c As Control In MyForm.Controls
Dim btt As Button = TryCast(c, Button)
If btt IsNot Nothing Then ' We got a button!
btt.Text = "foo"
End If
End For
Notice that this only works for controls that are directly on the form; controls nested into containers will not be iterated this way; you can however use a recursive function to iterate over all controls.
You can't create a control array in VB.NET, but you can archive similar functionality using the Handles keyword.
public sub Button_Click(sender as Object, e as EventArgs) Handles Button1.Click, Button2.Click, Button3.Click
'Do Something
End Sub
Yes, you can do this. But I don't think you can iterate buttons directly by giving myForm.
You create a Form and add a Layout 10 * 10, and try this,
Public Class Form1
Private NRow As Integer = 10
Private NCol As Integer = 10
Private BtnArray(NRow * NCol - 1) As Button
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
TableLayoutPanel1.Size = Me.ClientSize
For i As Integer = 0 To BtnArray.Length - 1
BtnArray(i) = New Button()
BtnArray(i).Anchor = AnchorStyles.Top Or AnchorStyles.Bottom Or AnchorStyles.Left Or AnchorStyles.Right
BtnArray(i).Text = CStr(i)
TableLayoutPanel1.Controls.Add(BtnArray(i), i Mod NCol, i \ NCol)
AddHandler BtnArray(i).Click, AddressOf ClickHandler
Next
End Sub
Public Sub ClickHandler(ByVal sender As Object, ByVal e As System.EventArgs)
MsgBox("I am button #" & CType(sender, Button).Text)
End Sub
End Class