How to add infinite components when a button is clicked - vb.net

I have a social media WinForm. I have a function that basically makes a new picture box when a button is clicked
Public Sub NewPost()
picture as new picturebox
picture.Width = 208
picture.Height = 264
picture.Image = Form2.PictureBox1.Image
picture.Location = New Point(258, 60)
End Sub
The thing is it only generates 1 new picture box because I have to make a new variable each time I want to add a picturebox, and eachtime I have to have a new name. I know my question Is a bit confusing but help would be nice thanks

If you want to trap events for your dynamic PictureBoxes, then you'll have to abandon the WithEvents model and move to using AddHandler.
Here's a quick example where the name of the PictureBox is displayed when it is clicked. Note that I am not setting a Location since they are being added to a FlowLayoutPanel which takes care of the placement for you:
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
NewPost()
End Sub
Public Sub NewPost()
Dim picture As New PictureBox
picture.Width = 208
picture.Height = 264
picture.BorderStyle = BorderStyle.FixedSingle
' ...etc...
Dim index As Integer = FlowLayoutPanel1.Controls.Count + 1
picture.Name = "pb" & index
AddHandler picture.Click, AddressOf picture_Click
FlowLayoutPanel1.Controls.Add(picture)
End Sub
Private Sub picture_Click(sender As Object, e As EventArgs)
Dim pb As PictureBox = DirectCast(sender, PictureBox)
Debug.Print(pb.Name)
End Sub
End Class

because I have to make a new variable each time
Not necessarily. You just want to keep a reference to the object. That reference doesn't need to be its own variable, it can just as easily be an element in a list. For example, suppose on your form you have a list of PictureBox objects as a class-level member:
Dim pictureBoxes As New List(Of PictureBox)()
Then in your method you can just add to that list:
Public Sub NewPost()
Dim pictureBox As New PictureBox
pictureBox.Width = 208
pictureBox.Height = 264
pictureBox.Image = Form2.PictureBox1.Image
pictureBox.Location = New Point(258, 60)
Me.pictureBoxes.Add(pictureBox)
End Sub
In this case the pictureBox variable is local to the NewPost method and gets re-created each time. But pictureBoxes is a class-level member and keeps track of the growing list of PictureBox objects that you're creating.

You can use a for while loop to create n number of objects

You can use the existing ControlCollection
Public Function NewPost() As String
Dim picture As New PictureBox
'your code
picture.Name = "Pb" & Form2.Controls.OfType(Of PictureBox).Count
Form2.Controls.Add(picture)
Return picture.Name
End Function
then you can retrive it
DirectCast(Form2.Controls(NewPost), PictureBox).Image = Form2.PictureBox1.Image
'OR
DirectCast(Form2.Controls("Pb12"), PictureBox).Image = Form2.PictureBox1.Image

Related

How to create an array of PictureBoxes and use it?

I thought "brickn()" will creat an array and "NoOfBrick" will be the array length and all array will store in it
Dim brickWidth as Integer = 0
Dim Brickn() As PictureBox
dim NoOfBrick as Integer ' array length
Public Function CreateBrick() As PictureBox
Dim myBrickn As New PictureBox
With myBrickn
.Size = Brick.Size
.Left = BrickWidth
.Top = 0
.Image = Brick.Image
.SizeMode = PictureBoxSizeMode.StretchImage
.BackColor = Color.Black
End With
Return myBrickn
End Function
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For i = -75 To Me.Width
Brickn(NoOfBrick) = CreateBrick() 'and also how to add array/list here
Me.Controls.Add(Brickn(NoOfBrick))
BrickWidth += 170 'increasing brick.left on every new brick is created
i += 170 ' increasing looop count according to brick needed
NoOfBrick +=1
Next
End Sub
But this code is throwing error on "Me.Controls.Add(Brickn(NoOfBrick))"
this error
System.NullReferenceException: 'Object reference not set to an instance of an object.'
I thought if I will get array of PictureBoxes then I can access control on them for this
Private Sub Boll_control_Tick(sender As Object, e As EventArgs) Handles Boll_control.Tick
If Ball.Bounds.IntersectsWith(brickn(NoOfBrick).Bounds) Then
Me.Controls.Remove(brickn(NoOfBrick))
End If
End Sub
Change:
Dim Brickn() As PictureBox
To:
Dim Brickn As New List(Of PictureBox)
Then, when you want to Add something to "Brickn", you'd do:
Brickn.Add(CreateBrick())
You can still access "Brickn" with array syntax, such as:
Brickn(NoOfBrick).Bounds
The difference is that a List will automatically grow or shrink in size as you add/remove things to it, while an Array has a fixed size (you never actually created the array in your code and gave it a size).
You can do hit testing with something like:
Dim hit = Brickn.Where(Function(brick) Ball.Bounds.IntersectsWith(brick.Bounds))
For Each brick As PictureBox In hit
Me.Controls.Remove(brick)
Brickn.Remove(brick)
Next

How to use properties of dynamically created picturebox in vb.net

I was trying to remove this "brickn" when ball intersect with this brick
but i am facing problem that "brickn" is not declared any helps?
there is code
Dim brickWidth as Integer = 0
Public Function CreateBrick() As PictureBox
Dim Brickn As New PictureBox
Me.Controls.Add(Brickn)
Brickn.Size = Brick.Size
Brickn.Left = BrickWidth
Brickn.Top = 0
Brickn.Image = Brick.Image
Brickn.SizeMode = PictureBoxSizeMode.StretchImage
Brickn.BackColor = Color.Black
Return Brickn
End Function
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For i= -75 To Me.Width
CreateBrick()
BrickWidth += 170 ' increasing brick.left on every new brick is created
i += 170 ' increasing looop count according to brick needed
Next
Private Sub Boll_control_Tick(sender As Object, e As EventArgs) Handles Boll_control.Tick
If Ball.Bounds.IntersectsWith(brickn.Bounds) Then
Me.Controls.Remove(brickn)
End If
End Sub
why this "brickn" is not saying not declared in "boll control tick " timer
You are instantiating brickn withing CreateBrick. You are returning it as the result of that function, but not assigning it to anything. So it's scope is limited to the CreateBrick fuction only, which is why it's not accessible from Boll_control_Tick.
Also you are then trying to create multiple instances of it with using a single object.
This code will allow you to create one or more. You will then need to rework your Boll_control_Tick to work out whether it intersects with any. You may want to create a list or array of PictureBox objects as Brickn instead of one.
Dim brickWidth as Integer = 0
Dim Brickn As PictureBox ' This may be better as a list or an array
Public Function CreateBrick() As PictureBox
Dim myBrickn As New PictureBox
'Note - no idea what Brick is here or where it comes from
Brickn.Size = Brick.Size
Brickn.Left = BrickWidth
Brickn.Top = 0
Brickn.Image = Brick.Image
Brickn.SizeMode = PictureBoxSizeMode.StretchImage
Brickn.BackColor = Color.Black
Return myBrickn
End Function
and then in your Form_Load method:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For i= -75 To Me.Width
Brickn = CreateBrick() ' or add to your List/Array here
Me.Controls.Add(Brickn)
BrickWidth += 170 ' increasing brick.left on every new brick is created
i += 170 ' increasing looop count according to brick needed
Next
That will add multiple picture boxes to your controls and, if you want, create a list or array of them for easy access. You will need to loop through those in Boll_control_Tick to see if ball bounds intersects with any and then remove that specific one only

How do I add then select the dynamic control I just added

I've got an application in VB.net which adds a picturebox to the selected mouse position within another picturebox control. I need to create a click event to select that new picturebox so I can drag it and drop it to a new location in the event that the first one was wrong or use a keypress event, those events I will code later, but I can not figure out how to select ANY of the dynamic controls.
In vb6 there was a way to select an index of the control, but there is no such animal in VB.net.
I've tried control groups, but for some reason I'm not getting results from them.
Here is the code I have so far
Private Sub PictureBox1_Click(sender As System.Object,
e As System.EventArgs) Handles PictureBox1.Click
Dim pb As New PictureBox
pb.BackColor = Color.Blue
Me.PictureBox1.Controls.Add(pb)
pb.Size = New Size(64, 110)
pb.Location = New Point(Cursor.Position.X - 64, Cursor.Position.Y - 110)
pb.Visible = True
End Sub
What in the name of all good things am I doing wrong here?
You need to write a generic event handler before time, using the sender parameter to refer to the object that raised the event.
Private Sub PictureBoxes_Click(sender As Object, e As EventArgs)
Dim pb = DirectCast(sender, PictureBox)
'Use pb here.
End Sub
When you create your control at run time, use an AddHandler statement to attach the method to the event.
Dim pb As New PictureBox
AddHandler pb.Click, AddressOf PictureBoxes_Click
That said, if you want to implement drag-n-drop then it's not the Click event you should be handling.
This little bit of code took some time, but I was able to do what I set out to so far...
This is before the Sub Main event
Public Class dynamicPB 'create a picturebox element which
'can be called anytime
Inherits PictureBox 'sets the type of control to a
'picturebox
Public Sub New() 'sets the function of the new box to
'default values
MyBase.BackColor = Color.AliceBlue
MyBase.BorderStyle = Windows.Forms.BorderStyle.Fixed3D
MyBase.Height = 50
MyBase.Width = 26
End Sub
End Class
in the actual main class
Private Sub <control_event> (blah...) Blah...
Dim intPosAdj_X As Integer = 13 'get an offset for the cursor
Dim intPosAdj_Y As Integer = 25
Dim newPictureBox As New dynamicPB 'sets the click of the mouse into a
'mode of drawing a new PB
With newPictureBox 'clean use of the code
AddHandler newPictureBox.Click, _
AddressOf PictureBox_Click 'establishes events for the mouse
'activity on the objects
AddHandler newPictureBox.MouseEnter, _
AddressOf PictureBox_MouseEnter
AddHandler newPictureBox.MouseLeave, _
AddressOf PictureBox_MouseLeave
pbName += 1 'gives a unique name to the
'picturebox in an "array" style
.Location = New System.Drawing.Point _
(xPos - intPosAdj_X, yPos - intPosAdj_Y) 'establish where the box goes
'and center the object on the
'mouse pointer
.Visible = True 'ensures that the box is visible
.Name = pbName 'names the new control
End With
Controls.Add(newPictureBox) 'add control to form
End Sub
Private Sub PictureBox_Click(sender As System.Object, e As System.EventArgs)
Dim dblMouseClick As Double = CType(DirectCast _
(e, System.Windows.Forms.MouseEventArgs).Button, MouseButtons) _
'make it simple to manipulate
'the event by putting the long
'code into a variable
If dblMouseClick = MouseButtons.Left Then
MsgBox("Left CLick")
ElseIf dblMouseClick = MouseButtons.Right Then
MsgBox("right click")
Else
MsgBox("Center")
End If
This actually resolves the issue of adding and being able to select the object
Thanks for all of the suggestions and help

How to manage dynamically created controls in VB.NET?

I just understand how to make controls dynamically in VB.NET (I mean, only part of adding a new one)
But, unlike VB6, it seems hard to handle those dynamic things.
When I click the DONE button, I want to make an array filled with the text of textboxes.
At the same time, I want to make a Delete button that removes the button itself and the textbox in the same line.
Is there any simple method or an sample code for this?
Thank you!
Drop a TableLayoutPanel on your form, called pnlLayout, and also the Add button called btnAdd. Configure TableLayoutPanel to have two columns, adjust column width as needed.
Paste below code into your form:
Public Class Form1
Dim deleteButtons As List(Of Button)
Dim textBoxes As List(Of TextBox)
Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
deleteButtons = New List(Of Button)
textBoxes = New List(Of TextBox)
End Sub
Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click
Dim elementCount As Integer = deleteButtons.Count
Dim txt As New TextBox
txt.Width = 100
txt.Height = 20
textBoxes.Add(txt)
Dim btn As New Button
btn.Width = 100
btn.Height = 20
btn.Text = "Delete " & elementCount.ToString
AddHandler btn.Click, AddressOf btnDelete
deleteButtons.Add(btn)
pnlLayout.SetCellPosition(txt, New TableLayoutPanelCellPosition(0, elementCount))
pnlLayout.SetCellPosition(btn, New TableLayoutPanelCellPosition(1, elementCount))
pnlLayout.Controls.Add(btn)
pnlLayout.Controls.Add(txt)
End Sub
Private Sub btnDelete(sender As Object, e As EventArgs)
Dim senderButton As Button = DirectCast(sender, Button)
Dim txt As TextBox = textBoxes(deleteButtons.IndexOf(senderButton))
pnlLayout.Controls.Remove(senderButton)
pnlLayout.Controls.Remove(txt)
End Sub
End Class
By default, it will have no textboxes and no Delete buttons, you can add as many rows of "Textbox + Delete button" as you want. When you press Delete, the row will be removed (and everything shifted to accommodate the empty space).
For the textbox'ex part:
Dim strcol() As String = {TextBox2.Text, TextBox3.Text}
For Each strtxt In strcol
MessageBox.Show(strtxt)
Next
It really depends on your code, but, if you have their name use this to delete the buttons &/ textbox'es:
For i As Integer = Me.Controls.Count - 1 To 0 Step -1
If TypeOf Me.Controls(i) Is TextBox Then
If Me.Controls(i).Name = "TextBox2" Then
Me.Controls.RemoveAt(i)
End If
End If
If TypeOf Me.Controls(i) Is Button Then
If Me.Controls(i).Name = "Button3" Then
Me.Controls.RemoveAt(i)
End If
End If
Next
But it depends on your code...

How to add event handler to a dynamically created control in VB.NET?

I have searched and seen countless samples here in this forum and in other sites but I'm still stuck with this problem;
I want to add a Click Handler for dynamically created PictureBox-es and pas an argument on it so I know which one of picture boxes was clicked).
Here is my current code:
Public Class frmMbarimAbonimi
Private Sub frmMbarimAbonimi_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'FitnessdbDataSet.clients' table. You can move, or remove it, as needed.
'Me.ClientsTableAdapter.Fill(Me.FitnessdbDataSet.clients)
'===============
Dim dt As DataTable = PaPaguar()
Dim i As Integer = 0
Dim gr(dt.Rows.Count) As GroupBox
Dim pp(dt.Rows.Count) As PictureBox
Dim lb(dt.Rows.Count) As Label
For Each row As DataRow In dt.Rows
gr(i) = New GroupBox
gr(i).Width = 200
gr(i).Height = 180
pp(i) = New PictureBox
pp(i).SizeMode = PictureBoxSizeMode.StretchImage
lb(i) = New Label
'-------------------------
Try
Using str As Stream = File.OpenRead("C:\Fotot\" + dt.Rows(i).Item("Foto"))
pp(i).Image = Image.FromStream(str)
End Using
lb(i).Text = dt.Rows(i).Item("Emer")
Catch ex As Exception
MsgBox("Fotoja nuk mund te ngarkohet, ju lutem realizoheni nje foto tjeter!!!")
End Try
'-------------------------
pp(i).Visible = True
pp(i).Width = 200
pp(i).Height = 150
AddHandler pp(i).Click, AddressOf testini
gr(i).Controls.Add(pp(i))
lb(i).Visible = True
lb(i).Width = 200
lb(i).Height = 30
lb(i).Left = pp(i).Left
lb(i).Top = pp(i).Top + 150
lb(i).BackColor = Color.WhiteSmoke
lb(i).BringToFront()
gr(i).Controls.Add(lb(i))
flpanel.Controls.Add(gr(i))
i = i + 1
Next row
End Sub
End Class
So I was trying to use AddHandler pp(i).Click, AddressOf testini but obviously this does not allow me to call "testini" with a parameter to identify which picture box was clicked.
Can someone point me in the right direction or give some advice? Greatly appreciated.
You need to add something to your created PictureBox to identify them in the event handler because you can't change the signature of the click event handler adding a 'parameter'
For example, you could set the Name property
pp(i) = New GroupBox
pp(i).Name = "PictureBox" + i.ToString
then in the event handler you could recognize your picture box casting the sender object to a picturebox and grabbing the Name property.
Remember, sender is always the control that triggers the event. In your case is always one of your dinamically created PictureBoxes
Private Sub testini(sender As Object, e As System.EventArgs)
Dim pb As PictureBox = DirectCast(sender, PictureBox)
Dim pbIdentity As String = pb.Name
.....
End Sub