I have a VB.net Windows form with a grid of Button controls. How best to capture the name of the buttons for a drag and drop operation? If I know the names of the source and destination buttons I can take appropriate action.
You can get the destination button and source button from arguments to the DragDrop handler
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' If buttons are on Panel1 then
' Me.Panel1.Controls().OfType(Of Button)()
' If buttons share some unique substring in name (to exclude other buttons)
' Me.Controls().OfType(Of Button)().Where(Function(b) b.Name.Contains("substring"))
Dim myButtons = Me.Controls().OfType(Of Button)()
' add all the event handlers to the buttons in the list
For Each b In myButtons
b.AllowDrop = True
AddHandler b.DragDrop, AddressOf Button_DragDrop
AddHandler b.DragEnter, AddressOf Button_DragEnter
AddHandler b.MouseMove, AddressOf Button_MouseMove
Next
End Sub
' standard event handler for drag enter
Private Sub Button_DragEnter(sender As Object, e As DragEventArgs)
If TypeOf e.Data.GetData(e.Data.GetFormats()(0)) Is Button Then e.Effect = DragDropEffects.Move
End Sub
' standard event handler for mouse move related to drag drop
Private Sub Button_MouseMove(sender As Object, e As MouseEventArgs)
If e.Button = MouseButtons.Left Then DoDragDrop(sender, DragDropEffects.Move)
End Sub
' the key is getting the source and destination from the arguments
Private Sub Button_DragDrop(sender As Object, e As DragEventArgs)
Dim destinationButton = DirectCast(sender, Button)
Dim sourceButton = DirectCast(e.Data.GetData(e.Data.GetFormats()(0)), Button)
MessageBox.Show($"Source: {sourceButton.Name}, Destination: {destinationButton.Name}")
End Sub
Related
Im currently trying to make dynamically created buttons disappear when clicked.
I have a Private Sub that handles when the button is clicked and increases the players score. However, i do not know how to make the specific object disappear as all the Objects are called the same name as they are created by the same subroutine set on a timer ( a new button made every 2 seconds).
I have tried adding every new button created to an array but am still struggling to make the program figure out which button has been clicked.
Any help would be greatly appreciated.
One of the parameters on your button click event handler should be sender As Object, which is a reference to the button that was clicked. You just need to cast it to a button object, the set the Visible property to false. Here is an example:
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim b As Button = CType(sender, Button)
b.Visible = False
End Sub
Further to #Icemanind's answer, you can actually do it in one line:
CType(sender, Button).Visible = False
This works without validation because you know that sender is of type Button.
If you have multiple buttons to handle, you can also add additional events to the handler so you don't end up with a zillion individual handlers:
Protected Sub Button_Click(s As Object, e As EventArgs) _
Handles _
Button1.Click, Button2.Click, Button3.Click
CType(s, Button).Visible = False
End Sub
Yet another option is to add the same handler to multiple buttons rather than adding buttons to the handler:
In Form instantiation (Sub New()):
AddHandler Button1.Click, AddressOf Button_Click
AddHandler Button2.Click, AddressOf Button_Click
AddHandler Button3.Click, AddressOf Button_Click
In Form class code:
Protected Sub Button_Click(s As Object, e As EventArgs)
CType(s, Button).Visible = False
End Sub
This last method works well with dynamic controls because you can add the handlers on the fly:
Dim button As Button
For i As Integer = 0 To 9
button = New Button With {.Name = $"Button{i}", .Text = $"Button{i}", .Left = 42, .Top = 50 + (i * 30)}
Me.Controls.Add(button)
AddHandler button.Click, AddressOf Button_Click
Next i
I have some simple code. It changes the BorderStyle property of a Label by right-clicking. Nothing fancy, but still. However, I have twenty labels. Is there a simpler way of doing this instead of "copy-paste" this code 20 times?
Private Sub Label1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles Label1.MouseDown
If e.Button = MouseButtons.Right Then
If Label1.BorderStyle = BorderStyle.None Then
Label1.BorderStyle = BorderStyle.FixedSingle
Else
Label1.BorderStyle = BorderStyle.None
End If
End If
End Sub
Private Sub Label2_MouseDown...
...
End Sub
You could either create a custom control which inherits from Label and has the behaviour you want, or you could write a handler which works out which control it is responding to from the sender parameter.
The latter, presented first here, is simpler for a one-off, but the former would be more re-usable, and you wouldn't have to maintain the list of Labels for the AddHandler.
Sub Label_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
Dim lbl = DirectCast(sender, Label)
If e.Button = MouseButtons.Right Then
If lbl.BorderStyle = BorderStyle.None Then
lbl.BorderStyle = BorderStyle.FixedSingle
Else
lbl.BorderStyle = BorderStyle.None
End If
End If
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For Each l In {Label1, Label2}
AddHandler l.MouseDown, AddressOf Label_MouseDown
Next
End Sub
The AddHandler line connects the MouseDown event of each of the Labels to the specified event handler. (You can add more than one event handler to an event, if needed.)
For a control (your very own custom one) derived from an existing control (a System.Windows.Forms.Label in this case), let's call it BorderedControl, you can follow the instructions at How to: Inherit from Existing Windows Forms Controls (it's too close to plagiarism to copy it to here), and then your code for the control might look like:
Public Class BorderedLabel
Inherits Label
Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
If e.Button = MouseButtons.Right Then
If Me.BorderStyle = BorderStyle.None Then
Me.BorderStyle = BorderStyle.FixedSingle
Else
Me.BorderStyle = BorderStyle.None
End If
End If
MyBase.OnMouseDown(e)
End Sub
Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
End Sub
End Class
After you have built your project after adding that code, you will find a new control, named "BorderedLabel", in the ToolBox. You can drag that onto the form "design surface" and it will behave just like an ordinary Label except that it will have your BorderStyle-changing code incorporated automatically.
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
can someone help me, how to create button/control like that in VB.NET .. that i mean, how to create/use style like that when i pointing the cursor or click the control, the style like transparent. that style different from button style.. please help me.. i have search everywhere but nothing. thank's before
Here is the image:
If you want to accomplish what you are looking for take a look at this example it might help you work out any issues you have:
Sub Main()
Dim myButton As Button = New Button()
myButton.Text = "Hello World"
myButton.BackColor = Color.Blue
myButton.FlatAppearance.BorderColor = Color.LightBlue
myButton.FlatAppearance.BorderSize = 2
AddHandler myButton.Click, AddressOf Me.OnMyButtonClick
AddHandler myButton.MouseHover, AddressOf Me.OnMyButtonEnter
AddHandler myButton.MouseLeave, AddressOf Me.OnMyButtonLeave
Panel1.Controls.Add(myButton)
End Sub
As you can see I have created a new button, and can modify all of the attributes of the button that you were looking for: Back color, Border color, and Border width, even the content like text or the image. Now you will want to create the events that will perform the actions that you are looking to accomplish:
Private Sub OnMyButtonClick(sender As Object, e As EventArgs)
Dim currentButton As Button = CType(sender, Button)
currentButton.Text = "I have been clicked!"
currentButton.BackColor = Color.LightBlue
currentButton.FlatAppearance.BorderColor = Color.Blue
currentButton.FlatAppearance.BorderSize = 1
End Sub
Private Sub OnMyButtonEnter(sender As Object, e As EventArgs)
Dim currentButton As Button = CType(sender, Button)
currentButton.BackColor = Color.LightGreen
End Sub
Private Sub OnMyButtonLeave(sender As Object, e As EventArgs)
Dim currentButton As Button = CType(sender, Button)
currentButton.BackColor = Color.Blue
End Sub
As you can see we have defined the 3 events you were looking to capture Mouse Click, Mouse Hover, and Mouse Leave, and within each one we can modify the button as we please. From here you can make a global parameter that monitors the color of the button, or you can monitor the state, from there you can know within each event what you want to do. Take for instance the Mouse Leave event.
You showed that you want to create a border, but have a white background as you can see, all you would have to do is just:
myButton.BackColor = Color.White
myButton.FlatAppearance.BorderColor = Color.LightBlue
That's easy enough, but there is one very important part that you need to know. If you want your button to actually perform events, ones that you created, you have to attach them to the button. Lets that a look at this:
AddHandler myButton.Click, AddressOf Me.OnMyButtonClick
AddHandler myButton.MouseHover, AddressOf Me.OnMyButtonEnter
AddHandler myButton.MouseLeave, AddressOf Me.OnMyButtonLeave
As you can see from the above code you instruct the program what to do when a certain event occurs such as Mouse Click. An important part to do with event handlers is to attach them after creation so that they will perform the actions right away. That is why I placed the attachment of the event handler in the Main() before I added the button to Panel1.
Let's try with this:
Import your image to resource.
You will need 3 different image: Normal, Hover and Clicked. Change this to your image name: CustomButtonN, CustomButtonH and CustomButtonC.
Add a Class with any name. Then add the code below:
Inherits Windows.Forms.Button 'To make this class as button command
Public Sub New()
Me.FlatStyle = Windows.Forms.FlatStyle.Flat 'Make it flat
Me.FlatAppearance.BorderSize = 0 'With borderless
Me.FlatAppearance.MouseDownBackColor = Color.Transparent 'You know this
Me.FlatAppearance.MouseOverBackColor = Color.Transparent 'And this
Me.BackColor = Color.Transparent 'Transparent key
Me.ForeColor = Color.Black 'Text color
Me.Width = 32 'Button width
Me.Height = 32 'Button height
Me.BackgroundImage = My.Resources.CustomButtonN 'Normal
Me.BackgroundImageLayout = ImageLayout.Stretch 'To stretch the image
End Sub
Private Sub CustomButton_MouseDown(ByVal sender As Object, _
ByVal e As MouseEventArgs) Handles Me.MouseDown
Me.BackgroundImage = My.Resources.CustomButtonC 'Click event
End Sub
Private Sub CustomButton_MouseHover(ByVal sender As Object, _
ByVal e As EventArgs) Handles Me.MouseHover
Me.BackgroundImage = My.Resources.MiniButtonH 'Hover event
End Sub
Private Sub CustomButton_MouseLeave(ByVal sender As Object, _
ByVal e As EventArgs) Handles Me.MouseLeave
Me.BackgroundImage = My.Resources.CustomButtonN 'Leave even
End Sub
Private Sub CustomButton_MouseUp(ByVal sender As Object, _
ByVal e As MouseEventArgs) Handles Me.MouseUp
Me.BackgroundImage = My.Resources.CustomButtonH 'Click release
End Sub
Note: You must compile the project after adding a class or editing:
Press F5 to start it and then wait for 3 sec, then stop it.
Finally see your Toolbox panel click your button name then put to your form.
As a new user to VB, I am struggling to see why this code works in one project but not in another. This code works fine if I create a new project and 2 new forms but when I place in my project, it doesn't fire at all on either left or right click.
I have tried a try/catch statement, but no errors are being reported. How do I go about troubleshooting this to find out the error. I have tried to rem out code and run after each comment but still the same. I have even tried removing all other code on the form leaving just the 2 subs but no joy. Any help would be greatly appreciated.
frmMain
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'StorageDataSet1.Customers' table. You can move, or remove it, as needed.
Me.CustomersTableAdapter.Fill(Me.StorageDataSet1.Customers)
'TODO: This line of code loads data into the 'StorageDataSet.User' table. You can move, or remove it, as needed.
Me.UserTableAdapter.Fill(Me.StorageDataSet.User)
'Dim frmDepartmentsLive As New frmDepartment
'frmDepartmentsLive.Owner = Me
'frmDepartmentsLive.ShowDialog()
lblDate.Text = Now
Timer1.Start()
rdoCustomer.Enabled = False
rdoCustomer.Checked = True
rdoDepartment.Enabled = False
rdoDepartment.Checked = False
For Each ctrl In Me.Controls
If TypeOf ctrl Is Button Then
AddHandler CType(ctrl, Button).MouseDown, AddressOf btn_MouseDown
End If
Next
End Sub
Private Sub btn_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs)
If (e.Button = MouseButtons.Right) Then
Dim btn = CType(sender, Button)
frmRacks.buttonName = btn.Name.Replace("btn", "")
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
Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
Me.Close()
End Sub
End Class
Since the controls are on a panel, they are members of that panel's controls array, not the form's. This -- and other things -- are apparent if you look thru the form's designer (on solution explorer, click Show All, then open formXXX.designer.vb). DOnt change anything, but it shows how controls are created and added. So...
For Each ctrl In thepanelName.Controls
If TypeOf ctrl Is Button Then
AddHandler CType(ctrl, Button).MouseDown, AddressOf btn_MouseDown
End If
Next
If it is ONLY those buttons on the panel you can short cut it:
For Each btn As Button In thepanelName.Controls
AddHandler CType(ctrl, Button).MouseDown, AddressOf btn_MouseDown
Next