Possible to select multiple tiles (pictureboxes) - vb.net

Hey so I'm trying to create this little bot.. However I got this code from a friend, it's a small 5x5 tiles, I can only select one tile with this and it will only use the one tile. I would like to be able to select multiple tiles and then the bot will also use the multiple tiles registered.
Tiles code is
Public Class Tiles
Private _activeTile As Integer = 0
Public ReadOnly Property activeTile As Integer
Get
Return _activeTile
End Get
End Property
Private Sub PictureBox_Click(sender As Object, e As EventArgs) Handles PictureBox1.Click, PictureBox2.Click, PictureBox3.Click, PictureBox4.Click, PictureBox5.Click, PictureBox6.Click, PictureBox7.Click, PictureBox8.Click, PictureBox9.Click, PictureBox10.Click, PictureBox11.Click, PictureBox12.Click, PictureBox13.Click, PictureBox14.Click, PictureBox15.Click, PictureBox16.Click, PictureBox17.Click, PictureBox18.Click, PictureBox19.Click, PictureBox20.Click, PictureBox21.Click, PictureBox22.Click, PictureBox23.Click, PictureBox24.Click, PictureBox25.Click
Dim p As PictureBox = TryCast(sender, PictureBox)
Dim id As Integer = CInt(p.Name.Split("x")(1))
If p.BorderStyle = Windows.Forms.BorderStyle.Fixed3D Then
p.BorderStyle = Windows.Forms.BorderStyle.None
p.BackColor = System.Drawing.Color.FromArgb(&HDD, &HDD, &HDD)
_activeTile = 0
Else
resetActiveTile()
p.BorderStyle = Windows.Forms.BorderStyle.Fixed3D
p.BackColor = System.Drawing.Color.FromArgb(&HA9, &HA9, &HA9)
_activeTile = id
End If
End Sub
Public Sub resetActiveTile()
For Each c As Control In Me.Controls
If c.Name.StartsWith("Pic") Then
Dim p As PictureBox = TryCast(c, PictureBox)
Dim id As Integer = CInt(p.Name.Split("x")(1))
p.BorderStyle = Windows.Forms.BorderStyle.None
p.BackColor = System.Drawing.Color.FromArgb(&HDD, &HDD, &HDD)
_activeTile = 0
End If
Next
End Sub
Private Sub Tiles_Load(sender As Object, e As EventArgs) Handles MyBase.Load
PictureBox1.BorderStyle = Windows.Forms.BorderStyle.Fixed3D
PictureBox1.BackColor = System.Drawing.Color.FromArgb(&HA9, &HA9, &HA9)
_activeTile = 1
End Sub
End Class
And here is the function where the active tile get used
Private Sub guess()
Try
If Tiles1.activeTile = 0 Then
BackgroundWorker1.CancelAsync()
MsgBox("Please select a tile!")
Else
s.Guess(currGame, Tiles1.activeTile)
End If
Catch ex As Exception
log(ex.ToString)
End Try
End Sub
Thanks a ton! :)

Related

snap to grid MDI child forms vb.net

I'm developping a modular dashboard in Visual Basic that starts as an empty container than i can add modules to populate it.
The parent form is an MDI container and every module is a child MDI form that have fixed size.
I'd like to snap all of that child form to a grid both when the user creates a new one and when moves one of it inside the container (like they are magnetized to that grid).
How can i do that? Thanks
If I well understand you need something like this:
Private Class ImaginaryGrid
' You can change Columns and Rows as you want
Shared Rows As Integer = 3
Shared Cols As Integer = 3
Private Shared Function SnapToGrid(target As Form) As Point
Dim AllW As Integer = Screen.PrimaryScreen.WorkingArea.Width
Dim AllH As Integer = Screen.PrimaryScreen.WorkingArea.Height
Dim parent = target.MdiParent
If parent IsNot Nothing Then
AllW = target.MdiParent.ClientSize.Width
AllH = target.MdiParent.ClientSize.Height
End If
Dim currentPoint As Point = target.Location
Dim stepW As Integer = CInt(AllW / Cols)
Dim stepH As Integer = CInt(AllH / Rows)
Dim targetCol As Integer = CInt(currentPoint.X \ stepW)
Dim targetRow As Integer = CInt(currentPoint.Y \ stepH)
Dim newX As Integer = targetCol * stepW
Dim newY As Integer = targetRow * stepH
target.Location = New Point(newX, newY)
target.Width = stepW
target.Height = stepH
End Function
Shared Sub AttachFormToStayInGrid(frm As Form)
AddHandler frm.ResizeEnd, Sub()
SnapToGrid(frm)
End Sub
SnapToGrid(frm)
End Sub
End Class
Usage:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
ImaginaryGrid.AttachFormToStayInGrid(Me)
End Sub
Take changes (if needed) as comments below shows:
Here's a beefed up version based on the same idea as G3nt_M3caj's suggestion:
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ImaginaryGrid.Client = Me.Controls.OfType(Of MdiClient).FirstOrDefault
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim frm As New Form
ImaginaryGrid.AttachFormToStayInGrid(frm)
End Sub
Private Class ImaginaryGrid
Public Shared WithEvents Client As MdiClient
Public Shared FixedChildSize As New Size(250, 150)
Private Shared Function SnapToGrid(target As Form) As Rectangle
Dim colX As Integer = target.Location.X / FixedChildSize.Width
Dim colY As Integer = target.Location.Y / FixedChildSize.Height
Dim newX As Integer = colX * FixedChildSize.Width
Dim newY As Integer = colY * FixedChildSize.Height
Return New Rectangle(New Point(newX, newY), FixedChildSize)
End Function
Shared Sub AttachFormToStayInGrid(frm As Form)
frm.Size = FixedChildSize
frm.FormBorderStyle = FormBorderStyle.FixedSingle
frm.MdiParent = Client.Parent
frm.Show()
SnapChild(frm)
AddHandler frm.ResizeEnd, Sub()
SnapChild(frm)
End Sub
AddHandler frm.LocationChanged, Sub()
If frm.WindowState = FormWindowState.Normal Then
snapRectangle = SnapToGrid(frm)
Client.Refresh()
End If
End Sub
End Sub
Private Shared Sub SnapChild(ByVal frm As Form)
If frm.WindowState = FormWindowState.Normal Then
Dim rc As Rectangle = SnapToGrid(frm)
frm.Bounds = rc
snapRectangle = Nothing
Client.Refresh()
End If
End Sub
Private Shared snapRectangle? As Rectangle
Private Shared Sub Client_Paint(sender As Object, e As PaintEventArgs) Handles Client.Paint
If snapRectangle.HasValue Then
e.Graphics.DrawRectangle(Pens.Black, snapRectangle)
End If
End Sub
End Class
End Class

PictureBox initial image

Is there a way that you can set all of the picboxes to a initial image when they are loaded? Such as: when you start a round, all the images are set to a image of a card facing down, then when the round starts it shows an image.
EDIT: How do I clear what is in the PicCard.Image?
Public Class Form1
Private Cards As New List(Of PictureBox)
Private randomnumber As Integer
Private HowManyCards As Integer
Private Sub SetupCards(numberofcards As Integer)
ClearGame()
For i As Integer = 0 To numberofcards
Dim PicCard As PictureBox = New PictureBox()
PicCard.Width = 100
PicCard.Height = 200
PicCard.Top = 50
PicCard.Left = 50 + PicCard.Width * i
Me.Controls.Add(PicCard)
PicCard.Image = imglistBackOfCard.Images(0)
Next i
End Sub
Private Sub ClearGame()
If Cards.Count > 0 Then
For i As Integer = 0 To Cards.Count - 1
Me.Controls.Remove(Cards(i))
Next
End If
' Clear the cards if they were already setup from a previous game.
Cards.Clear()
End Sub
Private Sub RandomCard()
Randomize()
randomnumber = Int(Rnd() * imglist1.Images.Count - 1) + 1
End Sub
Public Sub ShowCards(numberofcards As Integer)
For i As Integer = 0 To numberofcards
Dim PicCard As PictureBox = New PictureBox()
RandomCard()
PicCard.Width = 100
PicCard.Height = 200
PicCard.Top = 50
PicCard.Left = 50 + PicCard.Width * i
Me.Controls.Add(PicCard)
PicCard.Image = imglist1.Images(randomnumber)
PicCard.Tag = randomnumber
AddHandler PicCard.Click, AddressOf Me.cardflip_click
Cards.Add(PicCard)
Next i
End Sub
Private Sub StartGame_Click(sender As Object, e As EventArgs) Handles btnStartGame.Click
ShowCards(HowManyCards - 1)
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
HowManyCards = InputBox("How Many Cards?", "Please Enter")
SetupCards(Int(howmanycards - 1))
End Sub
End Class

Change foreground color of TreeView node from a seperated Thread

With the following code I fill a Treeview with a root node and several child nodes in the MainForm LoadEvent. With the button btnPing I go through the nodes and search for child nodes with level 2. These nodes are then queried with My.computer.network.ping and the ForeColor of the ChildNode is colored according to the result red or green. The whole works synonymous. However, the GUI freezes me every time.
'### TreeView Test
Option Explicit On
Option Strict On
Public Partial Class MainForm
Public Sub New()
Me.InitializeComponent()
End Sub
'### Hauptprogramm wird geladen ###
Sub MainFormLoad(sender As Object, e As EventArgs)
'Treeview befüllen
With treeView1
.Nodes.Add("Test1")
.Nodes(0).Nodes.Add("Test1_a")
.Nodes(0).Nodes.Add("Test1_b")
.Nodes(0).Nodes.Add("Test1_c")
.Nodes(0).Nodes(0).Nodes.Add("10.23.59.1")
.Nodes(0).Nodes(1).Nodes.Add("10.23.59.90")
.Nodes(0).Nodes(1).Nodes.Add("10.23.59.90")
.Nodes(0).Nodes(2).Nodes.Add("10.23.59.10")
.Nodes(0).Nodes(2).Nodes.Add("10.23.59.11")
.Nodes(0).Nodes(2).Nodes.Add("10.23.59.12")
.Nodes(0).Nodes(2).Nodes.Add("10.23.59.13")
.Nodes(0).Nodes(2).Nodes.Add("10.23.59.14")
End With
'Treeview aufklappen
treeView1.ExpandAll
End Sub
'### Sub zum rekursiven durchsuchen der Nodes ###
Private Sub RecurseNodes(ByVal col As TreeNodeCollection)
For Each tn As TreeNode In col
If tn.Level = 2 Then
Try
If My.Computer.Network.Ping(tn.Text) Then
tn.ForeColor = Color.Green
tn.StateImageIndex= 4
Else
tn.ForeColor = Color.Red
tn.StateImageIndex=5
End If
Catch ex As Exception
tn.ForeColor = Color.Red
tn.StateImageIndex=5
End Try
End If
If tn.Nodes.Count > 0 Then
RecurseNodes(tn.Nodes)
End If
Next tn
End Sub
'### Button zum starten der rekursiven Suche ###
Sub BtnPingClick(sender As Object, e As EventArgs)
'Treeview rekursiv durchsuchen
RecurseNodes(treeView1.Nodes)
End Sub
End Class
Now I would like to convert the whole so that the Ping runs in a separate thread. Now I have only one understanding question about the process. Can I start a thread with parameter transfer? Then I would run through the list and start with each node with level 2 a thread and wait for feedback. How would the best approach be?
Best Regards
Kay
Here's another approach:
Sub BtnPingClick(sender As Object, e As EventArgs)
'Treeview rekursiv durchsuchen
RecurseNodes(TreeView1.Nodes)
End Sub
Private Async Sub RecurseNodes(ByVal col As TreeNodeCollection)
For Each tn As TreeNode In col
If tn.Level = 2 Then
Dim T As Task(Of Boolean) = Ping(tn.Text)
Await T
tn.ForeColor = If(T.Result, Color.Green, Color.Red)
tn.StateImageIndex = If(T.Result, 4, 5)
ElseIf tn.Nodes.Count > 0 Then
RecurseNodes(tn.Nodes)
End If
Next tn
End Sub
Private Function Ping(ByVal ip As String) As Task(Of Boolean)
Return Task.Factory.StartNew(Of Boolean)(
Function() As Boolean
Try
Return My.Computer.Network.Ping(ip)
Catch ex As Exception
Return False
End Try
End Function)
End Function
Some ideas...
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim t As Task = Task.Run(Sub()
RecurseNodes(TreeView1.Nodes(0))
End Sub)
End Sub
Private Sub RecurseNodes(ByVal col As TreeNode)
For Each tn As TreeNode In col.Nodes
If tn.Level < 2 AndAlso tn.Nodes.Count > 0 Then
RecurseNodes(tn)
ElseIf tn.Level = 2 Then
Dim tp As Task
tp = Task.Run(Sub()
Dim c As Color
Dim idx As Integer
Try
If My.Computer.Network.Ping(tn.Text) Then
c = Color.Green
idx = 4
Else
c = Color.Red
idx = 5
End If
Catch ex As Exception
c = Color.Red
idx = 5
End Try
Me.Invoke(Sub()
tn.ForeColor = c
tn.StateImageIndex = idx
End Sub)
End Sub)
End If
Next tn
End Sub

Add Event to Picture Box dynamically vb.net

I'm trying to add pictureboxes dynamically in vb.net.
If i play with the vars, changing the "i" value i can add the images and the event to the last picturebox created (i can only click the last images).
But when i use the code below, it says the there's something out of boundaries ( Index outside the bounds of the matrix ).
What am i doing wrong? Tks
Imports System.IO
Public Class FormMain
Dim Path1 As String = Path.GetDirectoryName(Application.ExecutablePath) & "\Source\Images\1.png"
Dim Path2 As String = Path.GetDirectoryName(Application.ExecutablePath) & "\Source\Images\2.png"
Private Sub FormMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
CreateImages()
End Sub
Dim i As Integer
Dim Logo(i) As PictureBox
Sub CreateImages()
Dim i As Integer = TextBoxNumberImages.Text
For i = 0 To i - 1
Logo(i) = New PictureBox
Logo(i).Name = "Image" + Str(i)
Panel1.Controls.Add(Logo(i))
Logo(i).Image = Image.FromFile(Path1)
Logo(i).SizeMode = PictureBoxSizeMode.StretchImage
AddHandler Logo(i).Click, AddressOf _Click
Next
End Sub
'------ADD EVENT----
Dim IsImageSelected(i) As Boolean
Private Sub _Click(ByVal sender As Object, ByVal e As EventArgs)
If IsImageSelected(i) = False Then
Logo(i).Image = Image.FromFile(Path2)
IsImageSelected(i) = True
Else
Logo(i).Image = Image.FromFile(Path1)
IsImageSelected(i) = False
End If
End Sub
----EDIT----
I just changed the var declaration to inside of the function:
Sub CreateImages()
Dim i As Integer = TextBoxNumberImages.Text
Dim Logo(i) As PictureBox
For i = 0 To i - 1
Logo(i) = New PictureBox
Logo(i).Name = "Image" + Str(i)
Panel1.Controls.Add(Logo(i))
Logo(i).Image = Image.FromFile(Path1)
Logo(i).SizeMode = PictureBoxSizeMode.StretchImage
AddHandler Logo(i).Click, AddressOf _Click
Next
End Sub
Now it creates the images the way i want, but i can't access the pictureboxes in the event. Help?
Don't use an array, use a List(Of PictureBox) instead. You could also store the selected state in the Tag() of the PictureBox. To get a reference to the PictureBox that was clicked, cast the Sender parameter. All together it would look something like this:
Private Logo As New List(Of PictureBox)
Sub CreateImages()
Dim i As Integer = TextBoxNumberImages.Text
For i = 0 To i - 1
Dim pb As New PictureBox
pb = New PictureBox
pb.Tag = False ' <-- initial not selected state
pb.Name = "Image" + Str(i)
Panel1.Controls.Add(pb)
pb.Image = Image.FromFile(Path1)
pb.SizeMode = PictureBoxSizeMode.StretchImage
AddHandler pb.Click, AddressOf _Click
Logo.Add(pb)
Next
End Sub
Private Sub _Click(ByVal sender As Object, ByVal e As EventArgs)
Dim pb As PictureBox = DirectCast(sender, PictureBox)
Dim selected As Boolean = DirectCast(pb.Tag, Boolean)
If selected = False Then
pb.Image = Image.FromFile(Path2)
Else
pb.Image = Image.FromFile(Path1)
End If
pb.Tag = Not selected ' toggle selected state
End Sub

My counter adds 1 but doesn't update properly

This is a slot machine program. I am trying to detect how many times the user clicks a button (spins). But I can't figure out why my counter only adding 1 to my clickLabel? I'm sure it's a simple fix but I'm drawing a blank.
Public Class MainForm
Private Sub clickHereButton_Click(sender As Object, e As EventArgs) Handles clickHereButton.Click
' simulates a slot machine
Dim randGen As New Random
Dim leftIndex As Integer
Dim centerIndex As Integer
Dim rightIndex As Integer
Dim counter As Integer = 1
clickHereButton.Enabled = False
For spins As Integer = 1 To 10
leftIndex = randGen.Next(0, 6)
leftPictureBox.Image = ImageList1.Images.Item(leftIndex)
Me.Refresh()
System.Threading.Thread.Sleep(50)
centerIndex = randGen.Next(0, 6)
centerPictureBox.Image = ImageList1.Images.Item(centerIndex)
Me.Refresh()
System.Threading.Thread.Sleep(50)
rightIndex = randGen.Next(0, 6)
rightPictureBox.Image = ImageList1.Images.Item(rightIndex)
Me.Refresh()
System.Threading.Thread.Sleep(50)
Next spins
If leftIndex = centerIndex AndAlso
leftIndex = rightIndex Then
MessageBox.Show("Congratulations!", "Winner", MessageBoxButtons.OK, MessageBoxIcon.Information)
End If
counter += 1
clickLabel.Text = counter.ToString()
clickHereButton.Enabled = True
clickHereButton.Focus()
End Sub
Private Sub exitButton_Click(sender As Object, e As EventArgs) Handles exitButton.Click
Me.Close()
End Sub
End Class
What's happening is you're always setting the counter to 1 everytime you click the button because it is inside the clickHereButton_Click. So even though you are incrementing it, at the beginning of your sub you are still setting it to 1.
Dim counter As Integer = 1
Private Sub clickHereButton_Click(sender As Object, e As EventArgs) Handles clickHereButton.Click
...
End Sub