Creating Form Controls Programmatically

By Steven Hoffman
Comp 105BAS

Press enter to move through slides.

The "New" Keyword

A new form control can be created and assigned to a variable using the New keyword:

	Dim MyButton = New Button

You can then change the attributes of the button just like you normally would:

	MyButton.Text = "Submit"
	MyButton.Enabled = True

Changing Location and Size

In order to place the control on the form, we'll first need to set the Location and Size attributes. Location is the pixel width and height from the top left of whatever parent control (such as the form) we'll be adding this control to, and Size is width followed by height:

	' 100 pixels from the left, 200 pixels from the top
	MyButton.Location = New System.Drawing.Point(100, 200)
	
	' 50 pixels wide, 25 pixels tall
	MyButton.Size = New System.Drawing.Size(50, 25)

Location uses the System.Drawing.Point function to create a location that fits what Location wants, while Size uses System.Drawing.Size.

Adding the Control to the Form

Now that the button has a location and size, we can add it to the form using Me.Controls.Add():

	Me.Controls.Add(MyButton)

It should now appear on the form when the program is done, but it won't do anything. In order to make the button do something, we'll need to define a Sub and tell the control to use it.

AddHandler and AddressOf

First we have to create a Sub. It will be similar to those we already use, except it won't say what it handles.

	Private Sub MyClickHandler(ByVal sender As Object, ByVal e As System.EventArgs)
		MessageBox.Show("Sorry, you didn't win.")

		' In this sub, sender references the control that called the function, which is our button
		sender.Text = "Try Again"
	End Sub

Without going into too much detail, the AddressOf operator tells the program where to look for the function we want to use, and AddHandler tells the program to do something when a certain event happens. When put together, they assign a function to handle an event such as a button click:

	AddHandler MyButton.Click, AddressOf MyClickHandler

Now when the program is run, the button will execute the MyClickHandler Sub whenever it's clicked.

Put It All Together

	Private Sub MyClickHandler(ByVal sender As Object, ByVal e As System.EventArgs)
		MessageBox.Show("Sorry, you didn't win.")
	
		' In this sub, sender references the control that called the function, which is our button
		sender.Text = "Try Again"
	End Sub
	
	Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
		Dim MyButton = New Button
	
		MyButton.Text = "Submit"
		MyButton.Enabled = True
	
		' 100 pixels from the left, 200 pixels from the top
		MyButton.Location = New System.Drawing.Point(100, 200)
	
		' 50 pixels wide, 25 pixels tall
		MyButton.Size = New System.Drawing.Size(50, 25)
	
		AddHandler MyButton.Click, AddressOf MyClickHandler
	
		Me.Controls.Add(MyButton)
	End Sub

Where Does This Become Useful?

It would be useful to be able to create a three-dimensional array of buttons for something like a three-dimensional tic tac toe game. It's pretty easy to do when you create the buttons programmatically:

	Private Player1 = True
	Private Board(,,) As Button
	Private WhoWins = "X"
	
	Private Sub ClickHandler(ByVal sender As Object, ByVal e As System.EventArgs)
		If Player1 Then
			sender.Text = "X"
			Me.Text = "Player 2's Turn"
		Else
			sender.Text = "O"
			Me.Text = "Player 1's Turn"
		End If
	
		sender.Enabled = False
	
		Player1 = Not Player1
	
		' Pretend we have an isWinner() function
		If isWinner() Then
			If (WhoWins = "X") Then
				WinningPlayer = "Player 1"
			Else
				WinningPlayer = "Player 2"
			End If
			MessageBox.Show("We have a winner! " & WinningPlayer & " wins!")
		End If
	End Sub
	
	Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
		Board = New Button(4, 4, 4) {}
	
		For x = 0 To 4
			For y = 0 To 4
				For z = 0 To 4
					Board(x, y, z) = New Button
					Board(x, y, z).Text = ""
					Board(x, y, z).Location = New System.Drawing.Point(x * 30 + 16, z * 135 + y * 25 + 32)
					Board(x, y, z).Size = New System.Drawing.Size(30, 25)
	
					AddHandler Board(x, y, z).Click, AddressOf ClickHandler
	
					Me.Controls.Add(Board(x, y, z))
				Next
			Next
		Next
	
		Me.Text = "Player 1's Turn"
	End Sub