Create a new project.
Size of main form around: 660, 350
Add a listbox to the top left part of your form, size of the listbox: 160, 130
Below the listbox add a button, change text to: Remove
Below the button add a textbox, multiline yes, size around: 220, 70
On the top right of your form add a label, change text to: Add TextBox:
Below the label add 3 radio buttons, text of the first radio button: Bottom
second radio button text: Right
third radio button text: Custom
Below the radio buttons add a button, text: Create
Below this add another label.
Add a Timer to your program.
Click on the listbox1 -> Properties -> Items -> Click on the 3 dots -> Add: TextBox1 on the list -> OK
Click on the "Bottom" radio button, go to properties -> Checked: True
Click on Timer1 -> Properties -> Enabled: True
The program will allow adding textboxes on the main form. Each new textbox will be added to the listbox as it gets created.
First we will add the code that creates new textboxes. Every new textbox will have a name with a number higher than the previous one. We will need a variable for that. Right below "Public Class Form1" add:
Private mm As Integer = 2
-> we start at 2 because there's already one textbox on the main form.
Double click the "Create" button. Add this inside the sub:
Dim bbt As New TextBox
bbt.Name = "TextBox" & mm
bbt.Multiline = True
bbt.Height = TextBox1.Height
bbt.Width = TextBox1.Width
-> every new textbox will have this properties. Height and width are going to be the same as the textbox that is already present on the main form. We will need to specify a location for the new textbox, otherwise the coordinates will be 0,0 - which is not what we want.
The location is going to be determined depending on which radio button is checked.
If we choose the "bottom" option, than we will want for the new textbox to appear at the very bottom of all the previously created textboxes. We need a variable to help us always put our new textbox on the very bottom.
The same goes for the "right" option. So let's declare 2 new variables right below Private mm As Integer = 2
Private mm1 As Integer = 1
Private mm2 As Integer = 1
Inside the "create" button sub, below the previous code, add this:
If RadioButton1.Checked Then
bbt.Location = New Point(TextBox1.Location.X, TextBox1.Location.Y + mm1 * (TextBox1.Height + 10))
mm1 = mm1 + 1
End If
-> if the "bottom" radio button is checked, then the location of our new textbox is going to be:
TextBox1.Location.X
x is the horizontal pixel distance on your screen, it's going to be the same as textbox1 distance.
TextBox1.Location.Y + mm1 * (TextBox1.Height + 10) - y determines the vertical location on the screen, we start at the main vertical location of textbox1 and add the height of textbox1 and then 10 more pixels for the distance between the textboxes. Newly made textboxes will raise the "mm1" number which will ensure we always add the following on the bottom.
The same thing goes for the "right" option. Below the previous code add:
If RadioButton2.Checked Then
bbt.Location = New Point(TextBox1.Location.X + mm2 * (TextBox1.Width + 10), TextBox1.Location.Y)
mm2 = mm2 + 1
End If
-> if the "right" radio button is checked, add a new textbox on the right of the main starting textbox.
Below the previous code, still inside the sub of the "create" button, add:
Controls.Add(bbt)
ListBox1.Items.Add("TextBox" & mm)
mm = mm + 1
Controls.Add(bbt) - adds a new textbox inside the form. it gives it all the properties specified for "bbt".
ListBox1.Items.Add("TextBox" & mm) - this will add a textbox item in the listbox.
mm = mm + 1 - every new textbox will have a number higher by 1
The first 2 options should work now inside the program.
Code:
Public Class Form1
Private mm As Integer = 2
Private mm1 As Integer = 1
Private mm2 As Integer = 1
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim bbt As New TextBox
bbt.Name = "TextBox" & mm
bbt.Multiline = True
bbt.Height = TextBox1.Height
bbt.Width = TextBox1.Width
If RadioButton1.Checked Then
bbt.Location = New Point(TextBox1.Location.X, TextBox1.Location.Y + mm1 * (TextBox1.Height + 10))
mm1 = mm1 + 1
End If
If RadioButton2.Checked Then
bbt.Location = New Point(TextBox1.Location.X + mm2 * (TextBox1.Width + 10), TextBox1.Location.Y)
mm2 = mm2 + 1
End If
Controls.Add(bbt)
ListBox1.Items.Add("TextBox" & mm)
mm = mm + 1
End Sub
End Class
The "custom" option will wait for the user to make a click on the form which will decide the location of the new textbox. This means that we will have to take the coordinates of the cursor right after that click.
We have to declare a new variable that will store the coordinates of the mouse. At the start of the program, below the declarations of the other variables add this:
Private pp As New Point
Add this sub inside your code, below the previous sub:
Sub create(ByVal sender As System.Object, ByVal e As System.EventArgs)
pp = PointToClient(MousePosition)
RemoveHandler Click, AddressOf create
Button2_Click(Nothing, Nothing)
End Sub
-> the sub will collect the mouse coordinates inside the "pp" variable. It doesn't expect any events at the moment. We will add a "click" event to this sub inside of the third "custom" option in the previous sub, so that the following mouse click starts this sub.
We directly add the function to remove the "click" as event after we have received what we want.
Button2_Click(Nothing, Nothing) - we call button2 from here so that the program goes to the three code lines at the bottom. We will have to add a condition to the third "if" statement inside button2 so that it is not applied again on the following run through.
Inside the button2 sub, below this line:
bbt.Width = TextBox1.Width
add this:
bbt.Location = pp
-> if the "bottom" or "right" options are selected, the "bbt.location" value will be changed again.
Below the second "if" statement add the third option:
If RadioButton3.Checked And Label2.Text = "" Then
AddHandler Click, AddressOf create
Label2.Text = "! Select Location !"
Exit Sub
End If
-> if the third radio button is selected, this will then add a "click" event to the "create" sub. This happens after the "create" button is pressed. We avoid the creation of the textbox at the bottom of button2 by exiting.
The text of the label2 also gets changed here.
We use that to our favor, after the "create" sub takes the coordinates from the cursor, it returns the program to button2 which avoids the third "if" statement since the label2 has been changed.
Below the 3 code lines at the bottom of button2 add this:
Label2.Text = ""
Also, go to the design page, select a good location on your form for label2 -> go to properties -> erase all text from the text property. Now the text from label2 will only appear when we are selecting a custom location for our textbox.
At this moment, if you create objects that go over the borders of the main program form, there won't be any scrollbars appearing on the form so that you can actually scroll and see those objects. You have to go to the design page -> click on the blue header of the main form in order to select it -> Properties -> turn "AutoScroll" to true. They should appear now.
We will add the ability to select a textbox inside the listbox object (highlight it) and automatically change the borders of the same textbox inside our program. This way we visually know the location of the textbox we have selected in the listbox. Double click on the listbox, add inside the sub:
For Each i In Controls.OfType(Of TextBox)()
If i.Name = ListBox1.SelectedItem Then
i.BorderStyle = BorderStyle.FixedSingle
i.Focus()
Else
i.BorderStyle = BorderStyle.Fixed3D
End If
Next
-> The starting event of the listbox should be "SelectedIndexChanged", so the code of the listbox is started every time we select an item in it.
For Each i In Controls.OfType(Of TextBox)() - this will search through all the textboxes inside the whole program. The loop automatically stops when it reaches the last textbox.
If i.Name = ListBox1.SelectedItem Then - if the
name of the currently selected textbox in the "for" loop is equal to the name we have selected inside the listbox, then change the border style of that textbox and send the text cursor (the blinking line) inside the textbox. Under "else" all other textbox receive the default border style. This will all make the selected textbox appear as highlighted.
The opposite of the above operation would be: selecting a texbox inside the program form, and the selected item inside the listbox changing accordingly. To find out which textbox is currently focused on we will use the timer. Double click the Timer1 in the design page and add this inside the sub:
For Each i In Controls.OfType(Of TextBox)()
If i.Focused Then
ListBox1.SelectedItem = i.Name
End If
Next
-> when the timer locates the textbox that is focused on, it will take it's name and change the currently selected item in the listbox with this name.
We will use the button below the listbox to remove items from the list and the textboxes present inside the program. Double click on the "Remove" button and add this:
For Each i In Controls.OfType(Of TextBox)()
If i.Name = ListBox1.SelectedItem Then
Controls.Remove(Controls(ListBox1.SelectedItem))
End If
Next
ListBox1.Items.Remove(ListBox1.SelectedItem)
-> the "for" loop will take the name of the selected item in the listbox and find the desired textbox with it.
Controls.Remove(Controls(ListBox1.SelectedItem)) - this is how we remove a control from the form. We need to specify the name of the object inside the second parentheses to do that.
ListBox1.Items.Remove(ListBox1.SelectedItem) - this will remove the selected item from the listbox list. Putting the "for" loop below this line wouldn't give us what we want. The selected item would be erased and the loop wouldn't be able to use it to erase the object from the form.
Final code:
Public Class Form1
Private mm As Integer = 2
Private mm1 As Integer = 1
Private mm2 As Integer = 1
Private pp As New Point
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim bbt As New TextBox
bbt.Name = "TextBox" & mm
bbt.Multiline = True
bbt.Height = TextBox1.Height
bbt.Width = TextBox1.Width
bbt.Location = pp
If RadioButton1.Checked Then
bbt.Location = New Point(TextBox1.Location.X, TextBox1.Location.Y + mm1 * (TextBox1.Height + 10))
mm1 = mm1 + 1
End If
If RadioButton2.Checked Then
bbt.Location = New Point(TextBox1.Location.X + mm2 * (TextBox1.Width + 10), TextBox1.Location.Y)
mm2 = mm2 + 1
End If
If RadioButton3.Checked And Label2.Text = "" Then
AddHandler Click, AddressOf create
Label2.Text = "! Select Location !"
Exit Sub
End If
Controls.Add(bbt)
ListBox1.Items.Add("TextBox" & mm)
mm = mm + 1
Label2.Text = ""
End Sub
Sub create(ByVal sender As System.Object, ByVal e As System.EventArgs)
pp = PointToClient(MousePosition)
RemoveHandler Click, AddressOf create
Button2_Click(Nothing, Nothing)
End Sub
Private Sub ListBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListBox1.SelectedIndexChanged
For Each i In Controls.OfType(Of TextBox)()
If i.Name = ListBox1.SelectedItem Then
i.BorderStyle = BorderStyle.FixedSingle
i.Focus()
Else
i.BorderStyle = BorderStyle.Fixed3D
End If
Next
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
For Each i In Controls.OfType(Of TextBox)()
If i.Focused Then
ListBox1.SelectedItem = i.Name
End If
Next
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
For Each i In Controls.OfType(Of TextBox)()
If i.Name = ListBox1.SelectedItem Then
Controls.Remove(Controls(ListBox1.SelectedItem))
End If
Next
ListBox1.Items.Remove(ListBox1.SelectedItem)
End Sub
End Class
Start program.