Add event to dynamically created button - vb.net

I have 4 picture boxes on my form. Whenever a new picture is selected the next available box populated and a button is created within that picture box. I would like that button to be able to delete the image within that particular picturebox. I know how to create an event handler and then add the address to the button, what I do not know how to do is how to write the code so as to actually delete the assigned image on the assigned box. Here is my code to load the pictures and create the button:
Private Sub btnAddImage_Click(sender As Object, e As EventArgs) Handles btnAddImage.Click, btnUploadImage.Click 4
Dim btn As Button = New Button
btn.Text = "Remove Image"
'Procedure places the pictures in each empty picturebox in sequence
ofdBrowsePictures.Multiselect = False
ofdBrowsePictures.Title = "Select Image to Upload"
ofdBrowsePictures.Filter = "Image Files |*.jpg*"
If ofdBrowsePictures.ShowDialog() = Windows.Forms.DialogResult.OK Then
'create array of each picture box and check if they are empty
'Check if the picturebox contains a tag with the image path
Dim PBs() As PictureBox = {picMainImage, picImage2, picImage3, picImage4}
Dim nextPB = PBs.Where(Function(x) IsNothing(x.Image)).FirstOrDefault
If Not IsNothing(nextPB) Then
'if the box does not contain a image path, then place the picture on that box
nextPB.ImageLocation = ofdBrowsePictures.FileName
nextPB.Tag = nextPB.ImageLocation.ToString
'add a button
nextPB.Controls.Add(btn)
'Create a border style on the image
nextPB.BorderStyle = BorderStyle.FixedSingle
End If
End If
End Sub

what I do not know how to do is how to write the code so as to actually delete the assigned image on the assigned box
I assume "delete image" means remove from the picture box, not delete from disk.
' what is 4???
Private Sub btnAddImage_Click(sender As Object,
e As EventArgs) Handles btnAddImage.Click, btnUploadImage.Click 4
Dim btn As Button = New Button
btn.Text = "Remove Image"
' bla bla bla set the imagelocation
AddHandler btn.Click, AddressOf RemoveImage_Click
pb1.Controls.Add(btn) ' btn.parent = this pb
End Sub
Private Sub RemoveImage_Click(sender As Object, e As EventArgs) Handles Button9.Click
Dim btn As Button = CType(sender, Button)
' clear image
CType(btn.Parent, PictureBox).ImageLocation = ""
RemoveHandler btn.Click, AddressOf RemoveImage_Click
' remove the control
pb1.Controls.Remove(btn)
' if you remove a control, dispose of it
btn.Dispose()
End Sub
I am not sure I would invoke the dialog before checking for the next PB (nor would I create the new Button), since you seem to want to do nothing if there is no nextPB to play with.
For more information about Disposing of controls you Remove, see:
Memory Leak
What are Parking Windows
Adding / removing controls
Basically, forms dispose of controls when you close them. If you Remove a control, the form no longer has a reference and cannot. As a result, you should be disposing them.

Either of these clear a picturebox image set with ImageLocation:
PictureBox1.Image = Nothing
PictureBox1.ImageLocation = ""
PictureBox1.ImageLocation = String.Empty

Related

Identify buttons on click?

So here's what I have:
Code that makes buttons when you click the button "New Button" (Button1).
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
ActionsMade = ActionsMade + 1
Dim actionButton = New Windows.Forms.Button
ActionContainer.Controls.Add(actionButton)
actionButton.Text = "New Action " + ActionsMade.ToString
actionButton.Width = 107
actionButton.Height = 56
AddHandler actionButton.Click, AddressOf OnActionButtonClick
End Sub
When you click the buttons that were created, it shows an input box, where you type what you want to rename the button to.
Sub OnActionButtonClick()
If IsRenaming Then
Dim renameTo As String
renameTo = InputBox("Rename ActionButton To:")
Else
MessageBox.Show("Action started! Not renaming")
End If
End Sub
The only problem is, I have no way to identify between these buttons.
tl;dr:
I created buttons programmatically
I want to rename them
I don't know how to identify between these buttons and rename them individually
This is more concise and includes a referencable button name (eg Button_03):
Private Sub MakeButton_Click(sender As Object, e As EventArgs) Handles MakeButton.Click
Static ActionsMade As Integer = 0
ActionsMade += 1
ActionContainer.Controls.Add(New Button With {
.Name = $"Button_{ActionsMade:00}",
.Text = $"New Action {ActionsMade:00}",
.Size = New Size(107, 56),
.Location = New Point(100, 250 + 25 * ActionsMade)
})
AddHandler ActionContainer.Controls($"Button_{ActionsMade:00}").Click, AddressOf OnActionButtonClick
End Sub
Note that in the above code I haven't actually defined a new button per se, just New-ed it within the Controls.Add() statement, and then used the generated button name to add the event handler.
Another way would be declare the button as an independent object and then add it:
Dim actionButton As New Button With {
.Name = $"Button_{ActionsMade:00}",
.Text = $"New Action {ActionsMade:00}",
.Size = New Size(107, 56),
.Location = New Point(100, 250 + 25 * ActionsMade)
}
ActionContainer.Controls.Add(actionButton)
AddHandler actionButton.Click, AddressOf OnActionButtonClick
Other notes:
Use of a Static ActionsMade integer variable which retains its value between calls. This could also be a module-wide variable and removed from the MakeButton_Click Sub.
Use of string interpolation in assigning the button's Name and Text properties according to a formated version of the ActionsMade value.
Use of button properties Size and Location.
Automatic increment of button vertical position based on the value of ActionsMade.
Regarding your Action Button event handler, it should look like this:
Private Sub OnActionButtonClick(sender As Object, e As EventArgs)
If ActionStarted Then
MessageBox.Show("Action started! Not renaming.")
Else
CType(sender, Button).Text = InputBox("Rename ActionButton To:")
End If
End Sub
Note that I've checked for a started Action rather than a renaming in progress but that's just an illustration of an alternative approach. Note also that you don't need to know the name of the button to change its properties.

Open Tabs Control

I'm using MDI container to run my bussiness application I created for my client.
Since using MDI means that when I open several forms they will still run in background all the time untill I close them manualy.
What I need is to make User Control or anything else that could preview all opened forms in Tab Form so my client can easily close all or some of opened forms without closing a form he is curently viewing.
For now I have used this code, so for now only first clicked item from menu appears as button, but not others clicked menu items.
Private Sub MenuStrip1_ItemClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ToolStripItemClickedEventArgs) Handles MenuStrip1.ItemClicked
Dim Button As New Button
Me.Panel5.Controls.Add(Button)
Button.Text = e.ClickedItem.Name
Button.Width = 50
Button.Height = 25
End Sub
Now I need to write a code to add more buttons bellow, also should add a code for adding buttons only when I click on SubMenu item (The one when is clicked new Form appear).
And also, I should now add a little Close button into previewed User-Button-Control.
From your comments, I understand that your ideas regarding adding buttons at runtime are not too clear and thus I am including a small code which hopefully will help you on this front. Start a new project and put a Panel (Panel5) and a Button (AddButtons) on it, and write this code:
Dim lastButtonIndex, lastLeft, lastTop As Integer
Private Sub Button_Click(sender As System.Object, e As System.EventArgs)
Dim curButton As Button = DirectCast(sender, Button)
If (curButton.Name = "Button1") Then
'do Button1 stuff
End If
'etc.
End Sub
Private Sub addNewButton()
lastButtonIndex = lastButtonIndex + 1
lastLeft = lastLeft + 5
lastTop = lastTop + 5
Dim Button As New Button
With Button
.Name = "Button" + lastButtonIndex.ToString()
.Text = "Button" + lastButtonIndex.ToString()
.Width = 50
.Height = 25
.Left = lastLeft
.Top = lastTop
AddHandler .Click, AddressOf Button_Click
End With
Me.Panel5.Controls.Add(Button)
End Sub
Private Sub ButtonAddButtons_Click(sender As System.Object, e As System.EventArgs) Handles AddButtons.Click
addNewButton()
End Sub
This code will add a new button to the panel every time you click on AddButtons. All the buttons will have an associated Click Event (the same one for all of them): Button_Click. The way to know which button is the current one inside this method is via sender, as shown in the code (you can put as many conditions as buttons. The names are given sequentially starting from 1; but you can take any other property as reference, curButton is the given Button Control).
Bear in mind that one of the problems you have to take care of is the location of the buttons. The code above has a very simplistic X/Y values (Left/Top properties) auto-increase which, logically, will not deliver what you want.

How to change only one tooltip?

I am populating a FlowLayout with Pictureboxes. As I populate i give each of them a tooltip. I have a seperate function to change the pictures how can I change the tooltip as well?
dim laytt as tooltip = new tooltip
For i = 1 To count
Dim newPic As PictureBox = New PictureBox()
newPic.Image = p.Image
newPic.Size = p.Size
newPic.SizeMode = p.SizeMode
laytt.SetToolTip(newPic, ttstring)
AddHandler newPic.Click, AddressOf LayoutComponent_Clicked
sys.Add(a_component)
LayoutFlowLayout.Controls.Add(newPic)
Next
later i have a function to change the pics in it I want to be able to change the tool tip
Private Sub LayoutComponent_Clicked(ByVal sender As Object, ByVal e As EventArgs)
Dim i As Integer = LayoutFlowLayout.Controls.IndexOf(sender)
If deleteModeOn Then
sys.components.RemoveAt(i)
LayoutFlowLayout.Controls.RemoveAt(i)
Exit Sub
End If
'get index in sys from layout?
If (sys.components.Item(i).GetType() = GetType(Transpositor)) Then
Form2.ShowDialog(Me)
sys.components.Item(i).divert = tempTranspositorDivert
'here I want to do something like this
laytt.RemoveAt(i) <--- THIS DOESN'T EXIST
End If
End Sub
TL;DR I want to remove/change only one tooltip text at a specific index
Since the sender parameter is the picture box control that was clicked, you can use that variable to specify which control you want to alter. For instance, this will remove the tool tip:
laytt.SetToolTip(sender, Nothing)
This will change it:
laytt.SetToolTip(sender, "new value")

add on click event to picturebox vb.net

I have a flowLayoutPanel which I am programatically adding new panelLayouts to. Each panelLayout has a pictureBox within it. It's all working nicely, but I need to detect when that picture box is clicked on. How do I add an event to the picture? I seem to only be able to find c# examples....
my code to add the image is as follows...
' add pic to the little panel container
Dim pic As New PictureBox()
pic.Size = New Size(cover_width, cover_height)
pic.Location = New Point(10, 0)
pic.Image = Image.FromFile("c:/test.jpg")
panel.Controls.Add(pic)
'add pic and other labels (hidden in this example) to the big panel flow
albumFlow.Controls.Add(panel)
So I assume somewhere when I'm creating the image I add an onclick event. I need to get the index for it also if that is possible! Thanks for any help!
Use the AddHandler statement to subscribe to the Click event:
AddHandler pic.Click, AddressOf pic_Click
The sender argument of the pic_Click() method gives you a reference to the picture box back:
Private Sub pic_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim pic As PictureBox = DirectCast(sender, PictureBox)
' etc...
End Sub
If you need additional info about the specific control, like an index, then you can use the Tag property.
Substitute PictureBox1 with the name of your control.
Private Sub PictureBox1_Click(sender As Object, e As EventArgs) Handles PictureBox1.Click
'executes when PictureBox1 is clicked
End Sub

RichTextBox in VB.NET

I want set a line of text link in rich text box of vb.net. Like for example: I want to know you
The word want, I want to set a link word.
Can I do that?
This is how I would do it.
Dim linkLa As New LinkLabel
linkLa.LinkColor = Color.Red
Dim link As LinkLabel.Link = linkLa.Links.Add(0, 13, "http://www.stackoverflow.com")
linkLa.Text = "Stackoverflow"
AddHandler linkLa.LinkClicked, AddressOf Link_Clicked
richTextBox1.Controls.Add(linkLa)
Private Sub Link_Clicked(ByVal sender As Object, ByVal e As EventArgs)
MessageBox.Show("clicked")
End Sub
I have an answer for you. This will allow you to show the link target address as a tooltip. (little pop up bubble.) Other than that, it's similar to Stan R.'s answer.
Put this code under the "add link" button (or whatever you're calling it) in your program
Note: I put comments before each line, so it's easier to follow!
'define the text and link targets
Dim linktext As String = LinkTextbox.Text 'LinkTextbox is just the textbox where the user inputs the text of the link
Dim linktarget As String = LinkTargetTextbox.Text 'LinkTargetTextBox is just the textbox where the user inputs the target URL of the link
'Define the LinkLabel
Dim lnk As New LinkLabel
'if you want, you can set the different properties, like font or linkcolor, programmatically after defining the linklabel, for instance:
lnk.LinkColor = Color.Blue
'set tooltip
lnk.Tooltip = linktarget
'set the link target
Dim lk As LinkLabel.Link = lnk.Links.Add(0, 13, linktarget)
'set the link text
lnk.Text = linktext
'EventHandler
AddHandler lnk.LinkClicked, AddressOf LinkClicked
'Add the control to the richtextbox
RichTextBox1.Controls.Add(lnk)
'This is the Subroutine that the label will run when clicked (Make sure to put your "End Sub" before this, because it's not part of the button's subroutine)
Private Sub LinkClicked(ByVal sender As Object, ByVal e As EventArgs)
'send link to the browser
Process.Start(linktarget)
End Sub