Skipped naming the buttons because I'm lazy (seriously). Also Mutant's idea of having your own collection is a good one as it saves you having to iterate through ALL the controls on a form to find the dynamically generated controls.
The addhandler command is very powerful in this respect as it will allow you to declare event handlers at compile time and actually only wire up what is needed at run-time.
See modifications below
Private Buttons(9) As ButtonTextBox 'Put in the form declarations section
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim b As Button
Dim i As Integer
For i = 0 To 9
b = New Button
b.Location = New Point(10, i * 25)
b.Text = i
b.Name = "btn" & i.ToString() 'New line here
Me.Controls.Add(b)
TextBoxes(i)=b 'New line here
AddHandler b.Click, AddressOf ButtonClick
Next
End Sub
Private Sub ButtonClick(ByVal sender As Object, ByVal e As System.EventArgs)
Dim b As Button
b = DirectCast(sender, Button)
MessageBox.Show(b.Text)
End Sub
I always code with Option Strict On so just using sender.Text will generate an error.
The DirectCast is basically converting the generic sender object into a Button object - gives compile time checking of methods, events etc. The link dynamic_sysop gave explains it better than I could...