How to handle a variable amount of buttons clicked? - vb.net

I have a pretty basic problem with button clicks in VB.Net I cannot seem to figure out.
First, I am creating a variable amount of buttons and adding them to the parent form.
Private Sub CreateUIObjects()
For i As Integer = 1 To NumberOfButtons
Dim button As Button = New Button()
Me.Controls.Add(button)
Next
End Sub
I know it is possible to handle a fixed amount of buttons clicked with the following code
Private Sub Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles Button1.Click, Button2.Click, Button3.Click '... And so on
Dim b As Button = CType(sender, Button)
End Sub
But what do I do with not 3, but a variable amount of buttons?

Some code to experiment with
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
CreateUIObjects(3)
End Sub
Dim myButtonNames As String = "foobar"
Private Sub myButtonsClick(sender As Object, e As EventArgs)
Dim b As Button = DirectCast(sender, Button)
Debug.WriteLine(b.Name)
End Sub
Private Sub CreateUIObjects(NumberOfButtons As Integer)
Static ct As Integer = 0
For i As Integer = 1 To NumberOfButtons
ct += 1
Dim btn As Button = New Button()
btn.Name = myButtonNames & ct.ToString
btn.Text = btn.Name
btn.Location = New Point(ct * 20, ct * 20)
AddHandler btn.Click, AddressOf myButtonsClick
Me.Controls.Add(btn)
Next
End Sub

You can use something like this
AddHandler Button1.Click, AddressOf Button_Click
take a look http://msdn.microsoft.com/en-us/library/ms172877.aspx

Related

How can get the correct Handler of an object?

I am making an application that requires generating panels dynamically, and in turn that each panel generated two events, one with left click and another with right mouse click.
The right click is the one that gives me trouble since I have not been able to call a Handler that I have put temporarily in the event of the left click, but now that I see that it works, I want to pass it to the ToolStripMenuItem event, but when it enters event, the sender takes ownership of the ToolStripMenuItem and in this case you would need the property "System.Windows.Forms.Panel" in order to work on the Panel object.
I am not sure if I am doing it correctly, can you support me with any idea how to do it?
Annex the code of what I have developed so far
Public Class Form1
Dim pb, pbdoors As New Panel
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim pos As Int32 = 20
Dim contador As Int16 = 1
For i As Int16 = 1 To 3
Dim pb As New Panel With
{
.Width = 120,
.Height = 460,
.Top = 10,
.Left = 10,
.Name = "Panel" & contador,
.Location = New Point(pos, 20)
}
AddHandler pb.Click, AddressOf myClickHandler_b
Me.Panel1.Controls.Add(pb)
pb.BringToFront()
pos = pos + 120
contador = contador + 1
Next
End Sub
End Class
Public Sub myClickHandler_b(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim pos As Integer = Val(TextBox38.Text)
Dim clickedLabel As Panel = DirectCast(sender, Panel)
clickedLabel.Location = New Point((clickedLabel.Location.X + 120), clickedLabel.Location.Y)
TextBox38.Text = pos
End Sub
Private Sub ToolStripMenuItem1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripMenuItem1.Click
myClickHandler_b(sender, e)
End Sub
In order to recognize which mouse button is clicked you should use MouseClick as event handler.
The piece of code starting with and working on that is: “AddHandler pb.MouseClick……….”
I hope this might help you:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim pos As Int32 = 20
Dim contador As Int16 = 1
For i As Int16 = 1 To 3
Dim pb As New Panel With
{
.Width = 120,
.Height = 460,
.Top = 10,
.Left = 10,
.Name = "Panel" & contador,
.Location = New Point(pos, 20)
}
AddHandler pb.MouseClick, Sub(senderO As Object, eObj As MouseEventArgs)
If eObj.Button = MouseButtons.Left Then
'Do your tasks here
MsgBox("Left button clicked")
ElseIf eObj.Button = MouseButtons.Right Then
'Do your tasks here
MsgBox("Right button clicked")
End If
End Sub
Me.Panel1.Controls.Add(pb)
pb.BringToFront()
pos = pos + 120
contador = contador + 1
Next
End Sub
Winforms only provides a single event (Click) for both mouse buttons. You need to check (and cast, given that signature) the event arguments to know when you have a right click:
Public Sub myClickHandler_b(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim mouseevent As MouseEventArgs = TryCast(e, MouseEventArgs)
If mouseevent IsNot Nothing AndAlso mouseevent.Button = MouseButtons.Right Then
RightClick(TryCast(sender, Panel))
Exit Sub
End If
'Left Click
'Ugh. Val() is not your friend.
Dim pos As Integer = Val(TextBox38.Text)
Dim clickedLabel As Control = DirectCast(sender, Control)
clickedLabel.Location = New Point((clickedLabel.Location.X + 120), clickedLabel.Location.Y)
TextBox38.Text = pos
End Sub
Public Sub RightClick(source As Panel)
End Sub
Now for the second part. In the ToolStripMenuItem1_Click() method, if you have several dynamic panels on your form, how is the method supposed to know which panel it's working with? You need something in this code knows that information, and uses it for the sender argument. Additionally, given the new handling for left vs right clicks, you also need to think carefully about how that will spill over into the click handler.
So ToolStripMenuItem1_Click() should look something (but probably not exactly!) like this:
Private Sub ToolStripMenuItem1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripMenuItem1.Click
myClickHandler_b(pb, Nothing)
End Sub

Dynamically create multiple button and assign single click and double click comand

I created multiple button dynamically inside a panel based on multiple click on add button. Each button deletes When I click on it.
I want each button to delete when I single click on it, and say hello when I double click. Thank you.
I have tried using this code to delete which works fine, but I cannot figure how to assign seperate code to display hello when I double click or right click on it without affecting delete aspect of it.
Private Sub btnDynamic_Click(ByVal sender As Object, ByVal e As EventArgs)
'Reference the Button which was clicked.
Dim button As Button = CType(sender, Button)
'Determine the Index of the Button.
Dim index As Integer = Integer.Parse(button.Name.Split("_")(1))
'Find the TextBox using Index and remove it.
FlowLayoutPanel1.Controls.Remove(FlowLayoutPanel1.Controls.Find(("btnDynamic_" & index), True)(0))
'Remove the Button.
FlowLayoutPanel1.Controls.Remove(button)
'Rearranging the Location controls.
For Each btn As Button In FlowLayoutPanel1.Controls.OfType(Of Button)()
Dim controlIndex As Integer = Integer.Parse(btn.Name.Split("_")(1))
If (controlIndex > index) Then
Dim btn1 As Button = CType(FlowLayoutPanel1.Controls.Find(("btnDynamic_" & controlIndex), True)(0), Button)
btn1.Top = (btn.Top - 25)
'txt.Top = (txt.Top - 25)
End If
Next
End Sub
Here is the create button code:
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
If TextBox1.Text = "" Then
Exit Sub
End If
Dim count As Integer = Form2.FlowLayoutPanel2.Controls.OfType(Of Button).ToList.Count
Dim button As Button = New Button
button.Size = New System.Drawing.Size(28, 21)
button.Name = "btnDynamic_" & (count + 1)
button.Text = TextBox1.Text
AddHandler button.Click, AddressOf Me.button_click
Form2.FlowLayoutPanel2.Controls.Add(button)
End Sub
You have to enable DoubleClick option first.
You do so with:
Public Class DoubleClickButton
Inherits Button
Public Sub New()
SetStyle(ControlStyles.StandardClick Or ControlStyles.StandardDoubleClick, True)
End Sub
End Class
Then create a "DoubleClick" and "SingleClick" methods and assign them to (new custom) buttons when you are creating them.
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
For x = 0 To 2
Dim ButtonX As New DoubleClickButton
ButtonX.Text = x
AddHandler ButtonX.MouseClick, AddressOf SingleClickE
AddHandler ButtonX.MouseDoubleClick, AddressOf DoubleClickE
FlowLayoutPanel1.Controls.Add(ButtonX)
Next
End Sub
Private Sub SingleClickE(sender As Object, e As MouseEventArgs)
Debug.Print("Hello!")
End Sub
Private Sub DoubleClickE(sender As Object, e As MouseEventArgs)
FlowLayoutPanel1.Controls.Remove(sender)
End Sub
Thank you all for attempting to answer my question. I have been able to figure it out. I intend firing diffrent events with dynamically created buttons using single click, double click or right click. I ended up using single and right click command. Though would have prefered double click, but it is ok. Below is the code.
'Create buttons
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
For i As Integer = 1 To 5
Dim button As New Button
button.Text = i
AddHandler button.Click, AddressOf SingleClickE
AddHandler button.MouseDown, AddressOf RightClickE
FlowLayoutPanel1.Controls.Add(button)
Next
End Sub
'Fire it up with single click
Private Sub SingleClickE(sender As Object, e As MouseEventArgs)
Dim button As Button = CType(sender, Button)
MsgBox("Hello World")
End Sub
'Fire it up with Right Click
Private Sub RightClickE(sender As Object, e As MouseEventArgs)
Dim button As Button = CType(sender, Button)
If e.Button = MouseButtons.Right Then
FlowLayoutPanel1.Controls.Remove(button)
End If
End Sub

vb2010 getting name values from multiple buttons

At the moment, I have a button that sends a value to another form and displays result in a label. The problem is, I have 20 buttons that are labeled a to w that need to be coded and I am stumped as to how I can pass values from multiple buttons. Would it be a case statement in the form being passed to? I am a new user to VB.Net and still finding my way so any help would be gratefully received. I have included code sample for the first button 'A'. Thanks
frmMain
Private Sub btnA_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles btnA.MouseDown
If (e.Button = MouseButtons.Right) Then
'Dim curButton As Button = DirectCast(sender, Button)
'frmRacks.buttonName = curButton.Name 'Dynamic alternative to frmRacks.buttonName = "A"
frmRacks.buttonName = "A"
frmRacks.Show()
ElseIf (e.Button = MouseButtons.Left) Then
MessageBox.Show("To be coded")
End If
End Sub
frmRacks
Public Class frmRacks
Public buttonName As String
Private Sub racksfrm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
lblRacks.Text = buttonName
End Sub
EDIT: New project
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim button1 As Button = New Button
Dim button2 As Button = New Button
Dim button3 As Button = New Button
With button1
.Name = "button1"
.Left = 0
AddHandler .MouseDown, AddressOf btn_MouseDown
'Add remaining properties for button1
End With
With button2
.Name = "button2"
.Left = 100
AddHandler .MouseDown, AddressOf btn_MouseDown
'Add remaining properties for button2
End With
With button3
.Name = "button3"
.Left = 200
AddHandler .MouseDown, AddressOf btn_MouseDown
'Add remaining properties for button3
End With
Me.Controls.Add(button1)
Me.Controls.Add(button2)
Me.Controls.Add(button3)
End Sub
Private Sub btn_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs)
Dim curButton As Button = DirectCast(sender, Button)
Dim curButtonName As String = curButton.Name 'This string would change on account of the button you have clicked
Form2.buttonName = curButtonName
Form2.Show()
'MessageBox.Show("You clicked the button called " & curButtonName.ToUpper)
End Sub
End Class
Public Class Form2
Public buttonName As String
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
lblRacks.Text = buttonName
End Sub
End Class
Here you have a sample code which hopefully will help you to get clearer ideas:
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim button1 As Button = New Button
Dim button2 As Button = New Button
Dim button3 As Button = New Button
With button1
.Name = "button1"
.Left = 0
AddHandler .MouseDown, AddressOf btn_MouseDown
'Add remaining properties for button1
End With
With button2
.Name = "button2"
.Left = 100
AddHandler .MouseDown, AddressOf btn_MouseDown
'Add remaining properties for button2
End With
With button3
.Name = "button3"
.Left = 200
AddHandler .MouseDown, AddressOf btn_MouseDown
'Add remaining properties for button3
End With
Me.Controls.Add(button1)
Me.Controls.Add(button2)
Me.Controls.Add(button3)
End Sub
Private Sub btn_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs)
Dim curButton As Button = DirectCast(sender, Button)
Dim curButtonName As String = curButton.Name 'This string would change on account of the button you have clicked
MessageBox.Show("You clicked the button called " & curButtonName.ToUpper)
End Sub

How can I "compact" click events that use the same function?

I am creating a program that will allow a user to book seats in a theatre as a college project. It will feature a series of picture boxes that the user can click on to book a seat. The image in the picture box changes between the colour red and the colour green every time its pressed (if it is green, when it is clicked, it will become red etc.)
As for the function DetermineEnable, the value SeatNo represents the seat in the array enabled. This value is specific for each box (For seat A1, the seatno is 1). This value must remain the same, for the same box. The seatserial is just the name given to each picturebox (a1, a2, a3, a4, a5 etc).
I have only posted code for the first 5 seats, as this should give a general idea about what I'm asking.
What I'm asking is how can I "compact" all of the picturebox click events, So I only have to call the function "DetermineEnable" once or twice rather than 50+ times.
Many thanks!
' /// VISUAL AND INTERACTIVE DISPLAY
Sub DetermineEnable(ByVal SeatNo As Integer, ByVal SeatSerial As PictureBox)
If Enabled(SeatNo) = True Then
Enabled(SeatNo) = False
TotalCustomers = TotalCustomers - 1
ElseIf Enabled(SeatNo) = False Then
Enabled(SeatNo) = True
TotalCustomers = TotalCustomers + 1
End If
PictureLocation(SeatNo, SeatSerial)
UpdateEverything()
End Sub
Function PictureLocation(ByVal SeatNo As Integer, ByVal Picturebox As PictureBox) As String
If Enabled(SeatNo) = True Then
PictureLocation = "C:\Users\Wallace\Desktop\Theatre_Booking_System\enabled.png"
Else
PictureLocation = "C:\Users\Wallace\Desktop\Theatre_Booking_System\disabled.png"
End If
Picturebox.ImageLocation = PictureLocation
End Function
Private Sub a1_Click(sender As System.Object, e As System.EventArgs) Handles a1.Click
DetermineEnable(1, a1)
End Sub
Private Sub a2_Click(sender As System.Object, e As System.EventArgs) Handles a2.Click
DetermineEnable(2, a2)
End Sub
Private Sub a3_Click(sender As System.Object, e As System.EventArgs) Handles a3.Click
DetermineEnable(3, a3)
End Sub
Private Sub a4_Click(sender As System.Object, e As System.EventArgs) Handles a4.Click
DetermineEnable(4, a4)
End Sub
Private Sub a5_Click(sender As System.Object, e As System.EventArgs) Handles a5.Click
DetermineEnable(5, a5)
End Sub
Store the integer in the Tag property. Use the same sub to handle all the click events and cast the sender back to the PictureBox - which is the PictureBox that was clicked. a1.Tag = 1
Private Sub a1_Click(sender As System.Object, e As System.EventArgs) Handles a1.Click, a2,Click, a3.Click'etc...
Dim pb As PictureBox = DirectCast(sender, PictureBox)
DetermineEnable(Convert.ToInt32(pb.Tag), pb)
End Sub
Wire up the buttons in the Load() event, then extract the value from the name itself:
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim matches() As Control
For i As Integer = 1 To 50 ' <-- ajdust as necessary
matches = Me.Controls.Find("a" & i, True)
If matches.Length > 0 AndAlso TypeOf matches(0) Is PictureBox Then
Dim PB As PictureBox = DirectCast(matches(0), PictureBox)
AddHandler PB.Click, AddressOf pb_Click
End If
Next
End Sub
Private Sub pb_Click(sender As System.Object, e As System.EventArgs)
Dim PB As PictureBox = DirectCast(sender, PictureBox)
Dim value As Integer
If Integer.TryParse(PB.Name.TrimStart("a".ToCharArray), value) Then
DetermineEnable(value, PB)
End If
End Sub
Get rid of all the old hardcoded handlers for the PictureBoxes.
Something like this should work - put it in your Form_Load()...
Dim Pics = {a1, a2}
For i = 1 To Pics.Length
Dim Pic = Pics(i - 1)
AddHandler Pic.Click, Sub() DetermineEnable(i, Pic)
Next
If you don't want to define the list of controls manually, change
Dim Pics = {a1, a2}
to
Dim PicNamePattern As New System.Text.RegularExpressions.Regex("^a[0-9]*$")
Dim Pics = Me.Controls.Cast(Of Control).
Where(Function(x) PicNamePattern.IsMatch(x.Name))

How to make a click event for runtime created controls in Visual Basic 2010?

I added some controls to my form at runtime and I need them to call a function when clicked. I don't know how many controls will be added but they all need to run the same function. How would I define the event? Can I define events based on all controls of a given class?
A simple example :
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' creating control
Dim btn1 As Button = New Button()
Dim btn2 As Button = New Button()
btn1.Parent = Me
btn1.Name = "btn1"
btn1.Top = 10
btn1.Text = "Btn1"
btn2.Parent = Me
btn2.Name = "btn2"
btn2.Top = 50
btn2.Text = "Btn2"
'adding handler for click event
AddHandler btn1.Click, AddressOf HandleDynamicButtonClick
AddHandler btn2.Click, AddressOf HandleDynamicButtonClick
End Sub
Private Sub HandleDynamicButtonClick(ByVal sender As Object, ByVal e As EventArgs)
Dim btn As Button = DirectCast(sender, Button)
If btn.Name = "btn1" Then
MessageBox.Show("Btn1 clicked")
ElseIf btn.Name = "btn2" Then
MessageBox.Show("Btn2 Clicked")
End If
End Sub
End Class
Simply:
AddHandler Control.Event, AddressOf MethodExecuting
For example:
AddHandler Button1.Click, AddressOf ClickMethod