Random picturebox arrangement - vb.net

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

Related

Is it possible to group multiple PictureBoxes?

I can drag a PictureBox onto a Form Control, a Tab Control or a Panel Control, etc. And I can import an image into a PictureBox. However, I don't know how to group multiple PictureBoxes together in Visual Studio 2017. Looks like there is no such a function. I need this function because I want to generate a big picture based on the user's input. That big picture consists of multiple small pictures, the visibility of which is controlled by the user through multiple checkboxes.
In Excel, I could put multiple pictures in it, group them together, use the VBA to control the visibility of each picture, and finally copy that picture group into a Word file. I would do this in a VSTO Word Document project in Visual Studio 2017 using vb.net.
I added some pictures for demonstrate the expected function.
Picture 1 shows the small pictures to be used in a big picture. (Please ignore the .vslx file)
Picture 2 shows a possible result based on user's input.
You can make your own custom control. here is an example/suggestion how to do it with a User control that can be reused across your application. the user control is holding panels in a matrix, you can set a drag&drop Event to each Panel control and the user will be able to drop a picture box on each panel:
USER CONTROL:
Public Class UserControl1
Public NumberOfPanelsInRow As Integer
Sub New(ByVal height As Integer, width As Integer, Optional ByVal numberofPanelsInRow As Integer = 3)
' This call is required by the designer.'
InitializeComponent()
' Add any initialization after the InitializeComponent() call.'
Me.Height = height
Me.Width = width
Me.NumberOfPanelsInRow = numberofPanelsInRow
End Sub
Private Sub UserControl1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' grouped panels to hold picturebox you can drag & drop to them...'
Dim panelHeight As Integer = Me.Height / NumberOfPanelsInRow
Dim panelWidth As Integer = Me.Width / NumberOfPanelsInRow
Dim colors() As Color = {Color.Pink, Color.Black, Color.Red, Color.Cyan, Color.Green, Color.Orange,
Color.Red, Color.Pink, Color.Black, Color.Red, Color.Cyan, Color.Green, Color.Orange, Color.Red}
Dim total As Integer = NumberOfPanelsInRow * NumberOfPanelsInRow
Dim currentYlocation As Integer = 0
Dim currentXlocation As Integer = 0
Dim location As Point = New Point(0, currentYlocation)
Dim rowcounter As Integer = 0
Dim itemcounter As Integer = 0
For i = 1 To total
If rowcounter >= NumberOfPanelsInRow Then
rowcounter = 0
currentYlocation += panelHeight
currentXlocation = 0
End If
' to each one of this panel you can drag a picture box'
Dim p As New Panel
p.Size = New Size(panelWidth, panelHeight)
p.Location = New Point(currentXlocation, currentYlocation)
p.BackColor = colors(itemcounter)
Me.Controls.Add(p)
rowcounter += 1
itemcounter += 1
currentXlocation += panelWidth
Next
End Sub
End Class
CALLING THE USER CONTROL FROM FORM1:
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim uc = New UserControl1(300, 300)
Me.Controls.Add(uc)
End Sub
End Class
GUI OUTPUT:

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 do I detect collision with spawned objects?

Public Class Form1
Dim i As Integer 'integer for spawning
Dim maxball As Integer = 50 'max ball able to be created
Dim RateX(maxball) As Integer 'rate of movement
Dim RateY(maxball) As Integer 'rate of movement
Dim ball(maxball) As PictureBox 'spawned ball is a picture box
Dim rnd As New Random 'random number generator
Dim rndLoc As Integer 'random locatino generator
Dim Loc As Point 'location is a point on the screen
Dim create As Integer 'integer to create new balls
Dim score As Integer = 0 'score is 0 but can increase
'move the ball
Private Sub moveball()
'For Each ball(ec) In ball
For i As Integer = 0 To create - 1
If ball(i).Left <= pbArena.Left Then 'bounce off left side
RateX(i) *= -1
End If
If ball(i).Right >= pbArena.Right Then 'bounce off right side
RateX(i) *= -1
End If
If ball(i).Top <= pbArena.Top Then 'bounce off top
RateY(i) *= -1
End If
If ball(i).Bottom >= pbArena.Bottom Then 'bounce off bottom
RateY(i) *= -1
End If
'====================================================================================================================================================
ball(i).Left += RateX(i) 'moves the ball horizontally
ball(i).Top += RateY(i) 'moves the ball vertically
'====================================================================================================================================================
Next
End Sub
'create the ball
Private Sub createball()
If create <= 50 Then '50 is max amount to
create += 1 'add 1 to create
ball(i) = New PictureBox 'ball is a picture box
ball(i).Size = New Size(45, 45) 'set size
ball(i).BackColor = Color.Red 'set color
'====================================================================================================================================================
ball(i).Top = rnd.Next(pbArena.Height - ball(i).Height) 'sets random y
ball(i).Left = rnd.Next(pbArena.Width - ball(i).Width) 'sets random x
'====================================================================================================================================================
RateX(i) = rnd.Next(-4, 4) 'random X direction/speed
RateY(i) = rnd.Next(-4, 4) 'random Y direction/speed
'====================================================================================================================================================
Me.Controls.Add(ball(i)) 'actually add teh ball
ball(i).BringToFront() 'bring to front so arena isn't in front
i += 1
End If
End Sub
'commands for when you touch black box
Private Sub pbTarget_MouseEnter(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles pbTarget.MouseEnter
pbTarget.Top = rnd.Next(pbArena.Height - pbTarget.Height) 'sets random y
pbTarget.Left = rnd.Next(pbArena.Width - pbTarget.Width) 'sets random x
'====================================================================================================================================================
'scoring system
score = score + 1
lblScore.Text = score
createball() 'creates a new ball
End Sub
'what happens when the timer ticks
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
moveball() 'every timer tick the ball will move IF its created
ball(i) = New PictureBox 'ball is a picture box
End Sub
End Class
This is my code so far. Each time the mouse intersects with the target (which is a picture box) is moves. I am replicating this game. http://www.lewpen.com/game/ I have used an array to spawn red squares on the form. I want to be able to detect when my mouse enters them. I know how to do this with picture boxes, but these are all spawned objects called ball(i). Thanks for the help!
It sounds like you want to know how to add an event handler to a dynamically created control. these are all spawned objects called ball(i) but they are all just pictureboxes. You can add event handlers when you create the balls (pictureboxes)
Private Sub createball(BallIndex As Integer)
Dim ball As New PictureBox 'ball is a picture box
' give it a name so we can find it
' ball index is PASSED to avoid sloppy global vars
ball.Name = "Ball" & BallIndex.ToString
' etc
Me.Controls.Add(ball)
AddHandler ball.MouseEnter, AddressOf BallMouseEnter
Elsewhere, you'd add the code for the event:
Private Sub BallMouseEnter(sender As Object, e As EventArgs)
' your code here
End Sub
Since the balls exist as controls in the Controls collection there is really no reason to keep a reference to them in an array. If you name them "Ball1", "Ball2" you can make them move by referencing them by name:
Me.Controls(ballname)
Where BallName would be "Ball" & index.ToString and index would be the ball/picturebox to move (like the i variable). EDIT More info:
Private Sub moveballS()
Dim ball As PictureBox
' loop thru ballS
For n As Integer = 0 To BallCount
' current ball from name
ball = Me.Controls("Ball" & n.ToString)
' your code here
If ball.Left <= pbArena.Left Then
' etc
End If
' you CAN just reference them in controls(),
' but it is wordy:
If Controls("Ball" & n.ToString).Left <= pbArena.Left Then
' etc
End If
Next n
End Sub
Another way to track them is just a List(Of String) to store the name, but that is equally unneeded if you can get them by name from Controls() as above:
Dim ballList As New List(Of String)
' when you create a ball:
ballList.Add(ball.Name)
to get a control reference:
For n As Integer = 0 To ballList.Count - 1
ball = Me.Controls(ballList(n))
' etc
It can be a bad idea to create a separate reference to dynamically created controls (like an array) since that ref can prevent the object from being disposed of if/when you reset or start over and are deleting balls/pictureboxes.

Remove LineShape from Windows Form, LineShape and ShapeContainer Arrays

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

Minesweeper VB.NET issue

So basically, i have 2 int variables, x and y i am using to create a grid of pictureboxes.
This is all fluid and built on runtime.
I am trying to specifically change the picturebox on click if mine = 2.
I cannot specifically change one, when i click any, it changes all of them.
HELP PLEASE!!
Heres my code:
Public Class Form1
Inherits System.Windows.Forms.Form
Dim images(8) As Image 'declares image array
Dim zonesY As Integer = 50
Dim zonesX As Integer = 50
Dim Guy As Object
Dim pbxNewZone As PictureBox = DirectCast(Guy, PictureBox) 'declares pbxNewZone as a picturebox variable
Dim generator As New Random
Public Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
images(0) = Image.FromFile("blank.png")
images(1) = Image.FromFile("1.png")
images(2) = Image.FromFile("2.png")
images(3) = Image.FromFile("3.png")
images(4) = Image.FromFile("4.png")
images(5) = Image.FromFile("5.png")
images(6) = Image.FromFile("clear.png")
images(7) = Image.FromFile("hit.png")
images(8) = Image.FromFile("mine.png")
Dim x As Integer 'declares x as an integer variable
Dim y As Integer 'declares y as an integer variable
Me.SuspendLayout() 'suspends creation of layout
For y = 1 To zonesY 'starts a For loop (1 to zonesY number of loops)
For x = 1 To zonesX 'starts a For loop (1 to zonesX number of loops)
Dim zonesize1 As Integer
Dim zonesize2 As Integer
Dim mine As Integer
pbxNewZone = New PictureBox
Dim blockStatus As Integer
Dim allZones As Integer
allZones = zonesX * zonesY
blockStatus = generator.Next(0, allZones)
pbxNewZone.Name = (zonesX * (y - 1)) + x
If blockStatus < (allZones / 10) Then
mine = 1
If mine = 1 Then
pbxNewZone.Image = images(8)
End If
Else
mine = 2
If mine = 2 Then
pbxNewZone.Image = images(0)
End If
End If
pbxNewZone.Height = 16
pbxNewZone.Width = 16
pbxNewZone.Tag = 0
zonesize1 = pbxNewZone.Height 'sets out all of the boxes on the form.
zonesize2 = pbxNewZone.Width
pbxNewZone.Left = ((x - 1) * zonesize1 + 15)
pbxNewZone.Top = ((y - 1) * zonesize2 + 15)
Me.Controls.Add(pbxNewZone)
' Wire this control up to an appropriate event handler
AddHandler pbxNewZone.Click, AddressOf pbxNewZoneClicked
Next
Next
Me.Height = (pbxNewZone.Height * zonesY + 63) 'sets the height of fmmGame
Me.Width = (pbxNewZone.Width * zonesX + 40) 'sets the width of frmGame
checkBlank()
End Sub
Public Sub checkBlank()
End Sub
Private Sub pbxNewZoneClicked(ByVal sender As System.Object, ByVal e As System.EventArgs)
ReDim x
Do While y = 1 'starts a For loop (1 to zonesY number of loops)
Do While x = 1 'starts a For loop (1 to zonesX number of loops)
MsgBox("you have clicked " & x & ", " & y)
Loop
Loop
End Sub
End Class
You're adding the same handler to all the PictureBoxes but not doing anything to the specific PictureBox that was clicked (the Sender parameter). You can use the Name or Tag properties to work out what to do with the click. You might want to extend the standard PictureBox to include extra parameters that will make this easier - x and y properties for example.
As an aside you might want to consider re-factoring form_load so that it calls a number of more discrete methods.
In a Click event, sender will be the clicked object so...
Dim pbx as PictureBox = DirectCast(sender,PictureBox)
...will give you a reference (as pbx) to the clicked PictureBox - then you can do what you need to do with it.
For ease, you may want to check the state of a given PictureBox by checking pbx.Image - as you do not have any custom attributes of the PictureBox.