Remove LineShape from Windows Form, LineShape and ShapeContainer Arrays - vb.net

I am using the code below to add multiple LineShape controls to a Windows Form. Note the globally declared mLineShapes() and mShapeContainter() arrays (at bottom of code) which store each new LineShape object once it's created.
At present, I have been unsuccessful at removing a given LineShape control from the form (even if I know its array index), and also cannot removing an array element without causing a Nothing for the removed element. Obviously, once I remove the element from these arrays, it requires that all the remaining elements with greater indices are copied to lower values to fill in the Nothing voided element. Given these circumstances, can lists be used instead of the mLineShapes() and mShapeContainer() arrays?
enter code here' create new ShapeContainer
Dim sSCTemp As New ShapeContainer
' add ShapeContainer to Form
sSCTemp.Parent = Me
' create new LineShape
Dim sLSTemp As New LineShape
sLSTemp.BorderColor = Color.Black
sLSTemp.BorderWidth = 2
sLSTemp.Cursor = Cursors.Cross
' add LineShape to ShapeContainer
sLSTemp.Parent = sSCTemp
' set starting and ending coordinates for the line
sLSTemp.StartPoint = New System.Drawing.Point(siSCCount * 20, 60 + siSCCount * 60)
sLSTemp.EndPoint = New System.Drawing.Point(100 + siSCCount * 20, 110 + siSCCount * 60)
' set new LineShape to top of z-order
sLSTemp.BringToFront()
sSCTemp.BringToFront()
' connect ContextMenuStrip to LineShape
sLSTemp.ContextMenuStrip = mLsCtm1
' add new LineShape to arrays
ReDim Preserve mLineShapes(siSCCount)
ReDim Preserve mShapeContainer(siSCCount)
mLineShapes(siSCCount) = sLSTemp
mLineShapes(siSCCount).Name = "LineShape" & siSCCount
mShapeContainer(siSCCount) = sSCTemp
mShapeContainer(siSCCount).Name = "ShapeContainer" & siSCCount
In addition to the above, the endpoints of each
LineShape are selected from the arrays so that they can be moved. An example is below:
Dim siSCId As Integer
Dim myShapeContainer As ShapeContainer
myShapeContainer = CType(sender, ShapeContainer)
Dim myLineShape As LineShape
' get index of the actual ShapeContainer in ShapeContainer array
siSCId = Array.IndexOf(mShapeContainer, sender)
If siSCId > -1 Then
myLineShape = mLineShapes(siSCId)
If MouseIsNearBy(myLineShape.EndPoint) Then
myLineShape.BorderColor = Color.Red
NearLineEndPoint = True
End If
If MouseIsNearBy(myLineShape.EndPoint) = False Then
myLineShape.BorderColor = Color.Black
NearLineEndPoint = False
End If
If (dragStartPoint) Then
myLineShape.StartPoint = New Point(oldStartPoint.X + e.X - oldMouseX, oldStartPoint.Y + e.Y - oldMouseY)
End If
End If
Therefore, If I simply add a new LineShape to the form controls without using the mLineShapes() ans mShapeControl() arrays, how can I modify the above code (which finds the LineShape in the storage arrays) so that the line can be modified? I think that if I click on a LineShape, I can get its name using .sourcecontrol or .parent?
UPDATE 5/9/2019
After right clicking on a control on Form1 and selecting the "Link" command from a ContextMenuStrip, the following method (ctmsconnect) is fired to draw a new LineShape control that the user then drags and drops on to the next control in the workflow. Question is, is the list of LineShapes ("Lines") not needed?
(in Form1 class declarations):
Dim SC As New ShapeContainer
Dim Lines As New List(Of LineShape)
Private Sub ctmsconnect_Click(sender As System.Object, e As System.EventArgs) Handles ctmsconnect.Click
mLineWidth = 1
Dim myItem As ToolStripMenuItem = CType(sender, ToolStripMenuItem)
Dim cms As ContextMenuStrip = CType(myItem.Owner, ContextMenuStrip)
Dim x As Integer = cms.SourceControl.Right - 2
Dim y As Integer = cms.SourceControl.Top + (cms.SourceControl.Height / 2 - 12)
Dim LS As New LineShape
NumLineShapes += 1
LS.Name = "LineShape" & NumLineShapes
LS.BorderColor = Color.Black
LS.BorderWidth = 2
'Set starting and ending coordinates for the line
LS.StartPoint = New Point(x, y)
LS.EndPoint = New Point(x + 80, y - 5)
'Set new LineShape to top of z-order
LS.BringToFront()
Dim nxgContextMenuStrip As New ContextMenuStrip
LS.ContextMenuStrip = nxgContextMenuStrip
LS.Tag = "LineShape" & NumLineShapes & "_Delete"
'Attach an event handler for the ContextMenuStrip control's Opening event.
AddHandler nxgContextMenuStrip.Opening, AddressOf cms_Opening
numconnectedlineendpoints += 1
Dim myValues As New List(Of String)
myValues.Add(cms.SourceControl.Name)
DropLineOriginalObjectName = cms.SourceControl.Name
OrigDropControl = cms.SourceControl
myValues.Add(LS.Name)
myValues.Add("linestart")
dicGUIControls.Add(numconnectedlineendpoints, myValues)
Lines.Add(LS)
SC.Shapes.Add(LS)
Me.Refresh()
End Sub

You shouldn't need the arrays, just use the controls collection. Instead of setting the parent of the controls, you should probably add them to the collection:
'sSCTemp.Parent = Me
Me.Controls.Add(sSCTemp)
To remove them, you can reference them by the name property:
If Me.Controls.ContainsKey("ShapeContainer1") Then
Me.Controls.RemoveByKey("ShapeContainer1")
End If
The shape controls inside the ShapeContainer have to be accessed through the Shape collection:
If Me.Controls.ContainsKey("ShapeContainer1") Then
Dim sc As ShapeContainer = DirectCast(Me.Controls("ShapeContainer1"), ShapeContainer)
If sc.Shapes.ContainsKey("LineShape2") Then
sc.Shapes.RemoveAt(sc.Shapes.IndexOfKey("LineShape2"))
End If
End If
Example of reading the StartPoint and EndPoint properties:
Dim sb As New StringBuilder
For Each ls As LineShape In Me.ShapeContainer1.Shapes
sb.AppendLine(ls.StartPoint.ToString & " - " & ls.EndPoint.ToString)
Next
MessageBox.Show(sb.ToString)
Note: ShapeContainer Class makes a special note:
Be careful that you do not create more than one ShapeContainer for each form or container; doing this may introduce unexpected behavior. If you add a design-time line or shape control to a form or container after you write code to create one programmatically, you should modify that code to use the ShapeContainer created by the designer.

Public Class Form1
Dim canvas As New Microsoft.VisualBasic.PowerPacks.ShapeContainer
' Set the form as the parent of the ShapeContainer.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
canvas.Parent = Me
' Set the ShapeContainer as the parent of the LineShape.
End Sub
Private Sub Form1_MouseClick(sender As Object, e As MouseEventArgs) Handles Me.MouseClick
If RadioButton1.Checked = True Then
Dim line1 As New Microsoft.VisualBasic.PowerPacks.LineShape
line1.Parent = canvas
' Set the starting and ending coordinates for the line.
line1.StartPoint = New System.Drawing.Point(Me.Width / 2, 0)
line1.EndPoint = New System.Drawing.Point(e.X, e.Y)
TextBox1.Text = canvas.Shapes.Count.ToString
line1.Name = "MyShape"
canvas.Shapes.Add(line1)
AddHandler line1.Click, AddressOf LineClick
End If
End Sub
Private Sub LineClick(sender As Object, e As EventArgs)
' Here is where we take the object that is sender from the arguments and cast it to its specific control
If RadioButton2.Checked = True Then
' I could just as easily use
CType(sender, PowerPacks.LineShape).Dispose()
TextBox1.Text = canvas.Shapes.Count
End If
End Sub
End Class

Related

Random picturebox arrangement

I am new to visual basics and was wondering how to do the following program: I have 9 picture boxes and a button "arrange". For my program, I would like that all picture boxes come together like a puzzle randomly to make a square that has a width and height of three picture boxes. The square made would have all nine picture boxes in one and every time you click the button "arrange" the picture boxes would change to a random location within the square. So far, I have written so that all the picture boxes become the same size but i don't know how to make them come together in a square. Thanks in advance.
Public Class frm1
Dim Placement As Integer
Private Sub btnArrange_Click(sender As Object, e As EventArgs) Handles btnArrange.Click
picDeux.Size = picgris.Size
picTrois.Size = picgris.Size
picQuatre.Size = picgris.Size
picCinq.Size = picgris.Size
picSix.Size = picgris.Size
picSept.Size = picgris.Size
picHuit.Size = picgris.Size
picNeuf.Size = picgris.Size
lstNum.Items.Clear()
For i = 1 To 3
For j = 1 To 3
Dim L As New Point(picgris.Width * j + 100, picgris.Height * i)
lstNum.Items.Add(L)
Next
Next
For i = 1 To 3
For j = 1 To 3
Placement = Int(Rnd() * (lstNum.Items.Count))
Next
Next
End Sub
End Class
I created nine pictures boxes at design time. You would assign a different image to each picture box. They are all square and the same size. Mine are 100 x 100 to make the arithmetic easy.
I made an array of points as a form level variable. These point will form a 300 x 300 square with the picture boxes. I also declared an array of PictureBox. In the Form.Load I added the pictures boxes to the array.
To reposition the picture boxes assigned the array to a list. Items in this list will be removed because we don't want to assign the same location to more the one picture box. This will not effect the original array.
Looping through the picture boxes we assign a random position to the box then remove that point from the list.
Public Class PictureSort
Private Rand As New Random()
Private PointArray As Point() = {New Point(100, 100), New Point(200, 100), New Point(300, 100), New Point(100, 200), New Point(200, 200), New Point(300, 200), New Point(100, 300), New Point(200, 300), New Point(300, 300)}
Private PictureBoxArray(8) As PictureBox
Private Sub PictureSort_Load(sender As Object, e As EventArgs) Handles MyBase.Load
PictureBoxArray = {PictureBox1, PictureBox2, PictureBox3, PictureBox4, PictureBox5, PictureBox6, PictureBox7, PictureBox8, PictureBox9}
End Sub
Private Sub RepositionPictureBoxes()
Dim lst = PointArray.ToList
For Each pb In PictureBoxArray
Dim index = Rand.Next(0, lst.Count)
pb.Location = lst(index)
lst.RemoveAt(index)
Next
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
RepositionPictureBoxes()
End Sub
End Class
My advice is to use a control array - you have an example here that should help: VB.NET Control Array- Declaration and Application.
You just need to initiate that array of controls once, this can be done at form load.
The next step is to sort that array in a random manner. Finally, loop on the array and every time your current loop index modulo 3 = 0, then you increase the Y coordinates and reset the X position.
Here is an example. You can see that each time you click on the button, the picture boxes are rearranged on the form in random order using an ad hoc function. For each picture box, a bitmap is generated on the fly to show the index of the control.. this is for demonstration purposes.
Public Class frmPics
Private pics As New List(Of PictureBox)
Private Const picture_width As Integer = 100, picture_height As Integer = 50
Sub New()
' This call is required by the Windows Form Designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
' instantiate controls
Dim font As New Font("Arial", 20, FontStyle.Regular, GraphicsUnit.Pixel)
For i As Integer = 1 To 9
Dim pic As New PictureBox
pic.Visible = False
pic.Name = "pic" & i
pic.Text = i.ToString
Console.WriteLine("Create control: name: " & pic.Name)
' generate an ad-hoc bitmap image showing the index of the control
Dim bitmap As New Bitmap(picture_width, picture_height)
Using g As Graphics = Graphics.FromImage(bitmap)
Dim width As Integer = CInt(g.MeasureString(Text, font).Width)
Dim height As Integer = CInt(g.MeasureString(Text, font).Height)
End Using
Using g As Graphics = Graphics.FromImage(bitmap)
g.Clear(Color.Blue)
g.DrawString(i.ToString, font, New SolidBrush(Color.White), 0, 0)
End Using
pic.Image = bitmap
pics.Add(pic)
Me.Controls.Add(pic)
Next
End Sub
Private Sub btnShuffle_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnShuffle.Click
Dim x As Integer = 10, y As Integer = picture_height
Dim counter As Integer = 1
Dim rnd As New Random()
' show controls on form
Console.WriteLine("Show controls on form")
Me.SuspendLayout()
For Each item In pics.OrderBy(Function() rnd.Next)
item.Width = picture_width
item.Height = picture_height
item.Location = New Point(x, y)
item.BorderStyle = BorderStyle.FixedSingle
item.Visible = True
Console.WriteLine("counter: " & counter & " - control name" & item.Name & " - position: " & item.Location.X & "/" & item.Location.Y & " text: " & item.Text)
' reset X position every 3 iterations
If counter Mod 3 = 0 Then
x = 10
y += item.Height
Else
x += item.Width
End If
counter += 1
Next
Me.ResumeLayout()
End Sub
End Class

I'm trying to add pictureboxs to an array so I can reference them later as they are being created programmatically

So far all I have is this code...
Dim lineb As New PictureBox
lineb.Size = New Size(24, 24)
lineb.BackColor = Color.FromArgb(0, 192, 192)
lineb.Location = New Drawing.Point(xb, yb)
Controls.Add(lineb)
lineb.Name = "lineb" + CStr(creatorb)
creatorb += 1
This generates a infinite line of pictureboxs as it is inside a timer.tick event. Xb and Yb continuously move and this works. I need to figure out how to add each picturebox to an array or another way to reference them later. Each one gets created and renamed to lineb + 1...2...3...4... etc.
Here is an example of a way to keep track of dynamically created controls. It will be easier than adding every control to an array.
Dim pbox as New PictureBox
With pbox
.location = New Point(xb, yb)
.size = New Size(24, 24)
.Tag = "box1" 'choose a tag that will help identify it later
' and so on
Addhandler pbox.click, AddressOf pbox_click '' to add a click event handler
End With
Me.Controls.add(pbox)
Private Sub pbox_click(sender As Object, e As EventArgs)
Dim the_sender As PictureBox = DirectCast(sender, PictureBox)
Dim reference As String = DirectCast(the_sender.tag, String)
''' do whatever you need to do now that you know which picturebox was clicked.
End Sub
Alternatively you can always loop through your controls to find the one you are looking for:
For Each Ctrl As Control In Me.Controls
If TypeOf Ctrl Is PictureBox Then
If ctrl.tag = "box1" Then '''or whetever you are looking for
''' do your stuff here
End If
End If
Next

moving many controls together to represent a Seating Chart in VB.NET

Greetings,
I want To create a graphic representation of a seating chart (could be in a wedding venue or in cars...). I used a splitted panel, in the splittedPanel1 i put the buttons to create the cars, and inside the splitted panel2 i want to put the graphic representation. Inside SplittedPanel2, I've created a panel and a pictureBox (to represent some fixed areas in the real world).
I've also created a class called SimpleCar. SimpleCar is composed of 5 TextBox (es) and a PictureBox all in a panel to represent a car: the textBoses represent the passengers names and the car label, and the pictureBox to put an image representing a car (or a table). I've also made a sub to Add dynamically a SimpleCar.
2 problems occur when i want to move this new panel (dynamically created), using MouseDown and MouseUp events:
- first pb: while moving the existing panel, the screen flashes and the movement is not smooth
- second pb: i can't move a panel dynamically created
Note that moving a PictureBox by this code is very smooth but moving a panel is not user friendly.
I expect moving a dynamically created a panel smoothly, or should I reconsider displaying the cars in another way than in a panel?
Knowing that the final purpose of the code is to export a picture of all the created tables in the venue. I also tested the code with a groupBox and the results aren't good.
The simpleCar class is described in the code below:
Class SimpleCar
Public carNameBox, passengerNameBox1, passengerNameBox2,
passengerNameBox3, passengerNameBox4 As TextBox
Public carPictureBox As PictureBox
Public carGroup As Panel
Public Sub New()
carGroup = New Panel
carNameBox = New TextBox With {.Text = "carNmBx",
.BackColor = Color.Yellow,
.Name = "carNmBx"}
passengerNameBox1 = New TextBox With {.Text = "txtPassNmBx1",
.BackColor = Color.BlanchedAlmond,
.Name = "TextBox1"}
passengerNameBox2 = New TextBox With {.Text = "txtPassNmBx2",
.BackColor = Color.AliceBlue,
.Name = "TextBox2"}
passengerNameBox3 = New TextBox With {.Text = "txtPassNmBx3",
.BackColor = Color.Azure,
.Name = "TextBox3"}
passengerNameBox4 = New TextBox With {.Text = "txtPassNmBx4",
.BackColor = Color.Cyan,
.Name = "TextBox4"}
carPictureBox = New PictureBox With {.Text = "picBx1",
.BackColor = Color.BlanchedAlmond,
.Name = "picBox1"}
Dim fdialog As New OpenFileDialog()
fdialog.FileName = String.Empty
fdialog.Multiselect = True
If fdialog.ShowDialog = DialogResult.OK Then
If fdialog.FileNames.Length = 2 Then
carPictureBox.Image = Image.FromFile(fdialog.FileNames(0))
ElseIf fdialog.FileNames.Length = 1 Then
carPictureBox.Image = Image.FromFile(fdialog.FileName)
End If
End If
carGroup.Controls.Add(carPictureBox)
carGroup.Controls.Add(carNameBox)
carGroup.Controls.Add(passengerNameBox1)
carGroup.Controls.Add(passengerNameBox2)
carGroup.Controls.Add(passengerNameBox3)
carGroup.Controls.Add(passengerNameBox4)
End Sub
End Class
To Add dynamically a SimpleCar in the code below:
Public Sub Add_car()
Dim carType As SimpleCar
carType = New SimpleCar
Dim carPs1 = carType.passengerNameBox1
Dim carPs2 = carType.passengerNameBox2
Dim carPs3 = carType.passengerNameBox3
Dim carPs4 = carType.passengerNameBox4
Dim carNm = carType.carNameBox
Dim carPic = carType.carPictureBox
Dim carGroupBox = carType.carGroup
SplitContainer1.Panel2.Controls.Add(carGroupBox)
End Sub
So the problem occurs when i use this code to move a panel (if you replace PictureBox by Panel, even GroupBox) (it worked fine when I wanted to move one control: PictureBox1 in this sample):
'Drag To move PictureBox1 along with mouse-------------------------------------------
Dim oldX As Short
Dim oldY As Short
Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles PictureBox1.MouseDown
Dim X As Single = e.X
Dim Y As Single = e.Y
PictureBox1.Cursor = Cursors.SizeAll
oldX = CShort(X)
oldY = CShort(Y)
End Sub
Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs) Handles PictureBox1.MouseUp
Dim X As Single = e.X
Dim Y As Single = e.Y
PictureBox1.Cursor = Cursors.Default
End Sub
' to limit the movement within the app----------------------------------
Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles PictureBox1.MouseMove
If e.Button = MouseButtons.Left Then
Dim ProposedLocation As New Point(PictureBox1.Left - (oldX - e.X), PictureBox1.Top - (oldY - e.Y))
PictureBox1.Left = CInt(IIf(ProposedLocation.X < 0, 0, IIf(ProposedLocation.X > SplitContainer1.Panel2.Width - PictureBox1.Width, SplitContainer1.Panel2.Width - PictureBox1.Width, ProposedLocation.X)))
PictureBox1.Top = CInt(IIf(ProposedLocation.Y < 0, 0, IIf(ProposedLocation.Y > SplitContainer1.Panel2.Height - PictureBox1.Height, SplitContainer1.Panel2.Height - PictureBox1.Height, ProposedLocation.Y)))
End If
End Sub

Generating rows of panels with for loop in VB.NET

I would like to create rows of panels with textboxes using a for loop.
The panels will be created inside another panel (MajorPanel).
The for loop's current value is used to assign values to the textboxes.
The number of rows will be determined by a form (form2) that has a textbox (RowNum) to input number of rows needed in the main form (form1) and use that information for the for loop's counter as shown:
Public Class Form2
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Ok.Click
Dim Rows As Integer
Rows = RowNum.Text 'RowNum is where to input number of rows needed in form1
Dim TxtBoxPanel As New Panel
Dim LeftBox As New TextBox
Dim CenterBox As New TextBox
Dim RightBox As New TextBox
Dim YAxis As Integer ' for adding TxtBoxPanel in new row
For index = 1 To Rows
'adding the textbox panel
Form1.MajorPanel.Controls.Add(TxtBoxPanel) 'referring to form1 as panel needed in form1
TxtBoxPanel.Name = ("txtBoxPanel" & index)
TxtBoxPanel.Size = New Size(610, 32)
YAxis = +32
TxtBoxPanel.Location = New Point(3, YAxis)
'adding left box
TxtBoxPanel.Controls.Add(LeftBox)
LeftBox.Name = ("LeftBox" & index)
LeftBox.Text = (index)
LeftBox.Size = New Size(100, 20)
LeftBox.Location = New Point(3, 3)
'adding center box
TxtBoxPanel.Controls.Add(CenterBox)
CenterBox.Name = ("CenterBox" & index)
CenterBox.Text = (index)
CenterBox.Size = New Size(100, 20)
CenterBox.Location = New Point(258, 3)
'adding right box
TxtBoxPanel.Controls.Add(RightBox)
RightBox.Name = ("RightBox" & index)
RightBox.Size = New Size(100, 20)
RightBox.Text = (index)
RightBox.Location = New Point(495, 3)
Next index
Close()
End Sub
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles RowNum.TextChanged
End Sub
End Class
However, when I execute, the panels generate one on top of the other as shown:
After execution for 23 rows
This is the desired result I would like:
Rows of panels within MajorPanel
form1 has only one line of code:
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Form2.Show()
End Sub
End Class
In a quick glance, it looks like you are using YAxis = +32 when you should be using YAxis += 32.
The first one is just setting YAxis to the value 32, and the second one is incrementing it by 32, which is what you want (I assume)
There are two issues:
1- You are adding same instance of TxtBoxPanel to MajorPanel which means it will overwrite the previous location and you will end up only having single TxtBoxPanel at the bottom of MajorPanel because you are not creating new instead updating coordinates of same instance which got created before starting loop.
2- "YAxis = +32" should be "YAxis +=32
Here is updated code.. it should give you desired result.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Ok.Click
Dim Rows As Integer
Rows = RowNum.Text 'RowNum is where to input number of rows needed in form1
Dim YAxis As Integer ' for adding TxtBoxPanel in new row
For index = 1 To Rows
Dim TxtBoxPanel As New Panel
Dim LeftBox As New TextBox
Dim CenterBox As New TextBox
Dim RightBox As New TextBox
'adding the textbox panel
Form2.MajorPanel.Controls.Add(TxtBoxPanel) 'referring to form1 as panel needed in form1
TxtBoxPanel.Name = ("txtBoxPanel" & index)
TxtBoxPanel.Size = New Size(610, 32)
YAxis +=32
TxtBoxPanel.Location = New Point(3, YAxis)
'adding left box
TxtBoxPanel.Controls.Add(LeftBox)
LeftBox.Name = ("LeftBox" & index)
LeftBox.Text = (index)
LeftBox.Size = New Size(100, 20)
LeftBox.Location = New Point(3, 3)
'adding center box
TxtBoxPanel.Controls.Add(CenterBox)
CenterBox.Name = ("CenterBox" & index)
CenterBox.Text = (index)
CenterBox.Size = New Size(100, 20)
CenterBox.Location = New Point(258, 3)
'adding right box
TxtBoxPanel.Controls.Add(RightBox)
RightBox.Name = ("RightBox" & index)
RightBox.Size = New Size(100, 20)
RightBox.Text = (index)
RightBox.Location = New Point(495, 3)
Next index
Close()
End Sub

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