Control Array Examples Needed for Visual Studio 2013 - arrays

I know control arrays don't actually exist anymore, but I need something I can relate to my code. I'm making a shopping list game with a grid of 32 tiles that flip when clicked. They are actually PictureBoxes called pbxTile1 - pbxTile32. I sense you already know what I'm going to say.
A sample of my code:
Private Sub pbxTile1_Click(sender As Object, e As EventArgs) Handles pbxTile1.Click
If TileFlag(1) = 0 Then Exit Sub
My.Computer.Audio.Play(My.Resources.Tile_Flip, AudioPlayMode.Background) : Application.DoEvents()
Me.pbxTile1.BackgroundImageLayout = ImageLayout.Stretch
Me.pbxTile1.BackgroundImage = My.Resources.FLIP01 : Application.DoEvents() : System.Threading.Thread.Sleep(50)
Me.pbxTile1.BackgroundImage = My.Resources.FLIP02 : Application.DoEvents() : System.Threading.Thread.Sleep(50)
Me.pbxTile1.BackgroundImage = My.Resources.FLIP03 : Application.DoEvents() : System.Threading.Thread.Sleep(50)
Dim GroceryValue = TileItem(1)
Call Get_Grocery(GroceryValue)
Me.pbxTile1.BackgroundImageLayout = ImageLayout.None
Me.pbxTile1.BackgroundImage = My.Resources.ResourceManager.GetObject(GroceryResource) : Application.DoEvents()
You can see my problem - this is a fraction of the subroutine, which I need to recreate 32 times. But I'm sure one of you bright lads can come up with something to make it much less painful for me! I've seen tagging, and lists, and indexing - but not sure how to apply it, which is best, and need some examples please!

It's ok, I've found it! My word it works perfectly:
I didn't realise that Event Handlers can handle multiple Controls!
Instead of duplicating my code (32 times!) I just changed the Sub to:
Private Sub pbxTile_Click(ByVal sender As Object, e As System.EventArgs) Handles pbxTile1.Click, pbxTile2.Click, pbxTile3.Click, pbxTile4.Click, pbxTile5.Click, pbxTile6.Click, _
pbxTile7.Click, pbxTile8.Click, pbxTile9.Click, pbxTile10.Click, pbxTile11.Click, pbxTile12.Click, pbxTile13.Click, pbxTile14.Click, pbxTile15.Click, pbxTile16.Click, _
pbxTile17.Click, pbxTile18.Click, pbxTile19.Click, pbxTile20.Click, pbxTile21.Click, pbxTile22.Click, pbxTile23.Click, pbxTile24.Click, pbxTile25.Click, pbxTile26.Click, _
pbxTile27.Click, pbxTile28.Click, pbxTile29.Click, pbxTile30.Click, pbxTile31.Click, pbxTile32.Click
So basically if any of the 32 boxes are clicked, it calls the same Sub. And to differentiate between each PictureBox (this is the bit I was REALLY stuck on) I used DirectCast:
For z = 1 To 32
If DirectCast(sender, PictureBox).Name = "pbxTile" & z And TileFlag(z) = 0 Then Exit Sub
Next
I'm not sure if this is the most streamlined way, but it certainly works a treat, and saved me a bunch of code I didn't need!

Related

Changing control (that is in an array) from a timer: Not working

I'm trying to make a picture's visibility toggle on a timer. The picture I am trying to change is underscore(i). Here is that code:
Dim DigitSelected As Integer = 1
Public Underscores(3) As PictureBox
....
Private Sub CursorTimer_Tick(sender As System.Object, e As System.EventArgs) Handles CursorTimer.Tick
Me.Underscores(DigitSelected).Visible = Not (Me.Underscores(DigitSelected).Visible)
End Sub
This code above was previously working, but recently I moved where I was creating the pictureboxes and their stuff to a module on another page:
With Initials
For i As Byte = 1 To 3
.Underscores(i) = New PictureBox
With .Underscores(i)
.Height = 60
.Width = 144
.ImageLocation = "Underscore.png"
.BackColor = Color.Transparent
End With
.Controls.Add(.Underscores(i))
Next
end with
Now when I use the top-most snippet of code, it throws no errors, and changes nothing. I'm pretty sure I'm just missing something small.
Any ideas? Thanks!
I don't exactly know what you are trying to achieve here, but here is what happens :
Everytime you run that loop, you create three transparent PictureBox that you add to your Main Form. You don't remove anything, nor hide anything !
If you want to toggle visibility, that is no way of doing so !
The best would be for you to know the PictureBoxes names, so you can do :
Dim pb1 = CType(Initials.FindControl("MyPictureBox", true), PictureBox)
If Not IsNothing(pb1) Then
pb1.Visible = Not pb1.Visible
End If

WPF VB.Net ProgressBar updating in an Async Method

I've seen a few other posts about this but I seem to be confused since I've seen it done several ways and haven't gotten it correct any of the ways, so I thought I would ask specifically for my case so I can learn what I am doing wrong. After learning and switching to C# for most of my programming, VB.net seems so clunky in its syntax with a lot of things, especially lambda and "on-the-fly" functions.
I have a long running task for a football game I am working on where it generates players. Its an async method utilizing the Task.Factory.StartNew method.
Here is the pertinent code:
Private Sub CreateDraft_Click(sender As Object, e As RoutedEventArgs) Handles CreateDraft.Click
TimeIt(Sub() ReallyGenNewPlayers())
End Sub
'Uses a stopwatch to time how long it takes and sends to console.
Private Sub TimeIt(MyAction As Action)
Dim SW As New Stopwatch
SW.Start()
MyAction()
Console.WriteLine($"Total Time Generating Players: {SW.Elapsed} seconds")
SW.Stop()
End Sub
Private Async Sub GenNewPlayersASync()
Dim myvalue = 0
'Generate the Players on an Async Thread
Dim x As Integer
For i As Integer = 1 To NumPlayers
x = i 'avoids issue with using the iteration variable inside the delegate
CollegePlayers.GenDraftPlayers(i, MyDraft, DraftDT, DraftClass, PosCount)
'Prog_ValueChanged(DBNull.Value, New RoutedPropertyChangedEventArgs(Of Double))
'Calls a delegate to update the progress bar to avoid having the variable locked by the background thread
Dispatcher.Invoke(Sub()
worker.ReportProgress((x / NumPlayers) * 100)
End Sub)
Next i
End Sub
'Creates a task to run the player generation code and wait til its finished
Private Sub ReallyGenNewPlayers()
Dim mytask = Task.Factory.StartNew(Sub() GenNewPlayersASync())
Task.WaitAll(mytask)
End Sub
So here is what I would like to do:
I have a progressbar I created in XAML that has a Progress_Changed Event. This is what I have for it so far based on another post, but the issue is when I have to call the function inside GenNewPlayersAsync() where it wants a RoutedPropertyChangeEventArgs as a double which I'm not exactly sure what to do...I tried creating one using .New(old value, new value) but that didn't work either and threw an error.
Public Async Sub Prog_ValueChanged(sender As Object, e As RoutedPropertyChangedEventArgs(Of Double))
Dim progress = New Progress(Of Integer)(Function(percent)
Prog.Value = e.NewValue
Return Prog.Value
End Function)
Await Task.Run(Sub() DoProcessing(progress))
End Sub
Public Sub DoProcessing(progress As IProgress(Of Integer))
Dim i As Integer = 0
While i <> 100
Thread.Sleep(100)
' CPU-bound work
If progress IsNot Nothing Then
progress.Report(i)
End If
End While
End Sub
I would like for the progressbar to be bound to an INotifyChanged Property and update itself automatically when the value gets changed. None of it seems to be working. The UI is still unresponsive and when I set different parts to ASync, I start getting Exceptions where it appears certain parts of the generation algorithm aren't working as they are returning null...very confused with all of this, and I am sure the answer is probably pretty simple...
If you guys could give several examples of different ways to get this to work so I can learn different methods and maybe state the pros and cons of the method I would greatly appreciate it...

GetAsyncKeyState to repeat same key

Imports InputManager
'Using inputmanager to send keys
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
hotkeyx = GetAsyncKeyState(Keys.X)
If hotkeyX < 0 Then
Keyboard.KeyUp(Keys.X)
System.Threading.Thread.Sleep(5)
Keyboard.KeyDown(Keys.X)
System.Threading.Thread.Sleep(5)
End If
'Timer1 interval is 10 ms
The problem is if I do this, when I press and hold X for about 5 seconds then
it will just repeat X indefinitely even if I release the X key.
I only want X repeated when I hold down X key then I want it to stop when I release it.
Help me please.
If I add, Keyboard.KeyUp(Keys.X) following Keyboard.KeyDown(Keys.X) then it will not repeat it when I release the key but then the key will be repeated much slower and GetAsyncKeyState will take longer to detect the key press so I can't do that. – user1785594 2 hours ago
Also If I increase Timer1 interval to 50 ms, then async repeat problem will become less frequently but it still does that and I don't think that's the right way to do it.
Dim cntNo As Int32 = 0
Private Sub CheckKey(ByVal key As Integer)
Dim state = GetAsyncKeyState(key)
If state < 0 Then
prevState(key) = True
Keyboard.KeyUp(CType(key, Keys))
'keyup to simulate X keyUp for target program
System.Threading.Thread.Sleep(5)
'5ms interval is required for me
Keyboard.KeyDown(CType(key, Keys))
System.Threading.Thread.Sleep(5)
'Above code is much better than previous one but it does unintended async repeat sometimes
cntNo = cntNo + 1
If cntNo > 10 Then
Keyboard.KeyUp(CType(key, Keys))
cntNo = 0
End If
'If it's repeated for 10 times then send keyUP to end it
ElseIf prevState(key) Then
prevState(key) = False
Keyboard.KeyUp(CType(key, Keys))
End If
End Sub
Private Sub Timer4_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer4.Tick
CheckKey(Keys.X)
End Sub
'-Thanks to Hans Passant, I made a working code but I think I used improper way to do this though.
Since program require keyUP to simulate X key press, it will have the same problem although not as often as before, I don't know how to solve it so I just added key up for every 10 rounds. Is there a better solution?
The code snippet is strange, it generates a KeyUp notification when the key is down. You can normally rely on the value returned by GetAsyncKeyState() to detect a key-up state, bit #0 will be set if the key was previously down. But that's pretty unlikely to work correctly when you also have a Timer ticking, clearly your code has a dispatcher loop.
So you need to keep track of the previous value to detect the key-up state:
Private prevState(255) As Boolean
Your timer Tick event handler now just need to update this array and generate the notification as desired. Making it as generic as possible:
Private Sub CheckKey(key As Integer)
Dim state = GetAsyncKeyState(key)
If state < 0 Then
prevState(key) = True
Keyboard.KeyDown(CType(key, Keys))
ElseIf prevState(key) Then
prevState(key) = False
Keyboard.KeyUp(CType(key, Keys))
End If
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
CheckKey(Keys.X)
End Sub
Declare Function GetAsyncKeyState Lib "user32.dll" (key As Integer) As Short
Do beware of the failure modes of code like this. If the key is held down for a very short time, less than the timer's Interval, then you'll completely miss it. You are much better off using the operating system's provided KeyUp/Down events, you can never miss those. Just use that same array to generate the events. And you cannot rely on a 10 msec timer interval, the default is 15.625 msec.

Manipulating Array After Pulling From Text File

I've been thoroughly combing StackOverflow and other sources for the answers to these problems, and have not been able to find a solution that would work cohesively with the steps I need to accomplish.
Things I need to do:
Create an array from a text file and display in a listbox (this is done and works)
Have user fill in a text box, click a button, and the array is searched for anything matching the text box's value
Have the results of the search displayed in a separate listbox
Here's what I've got so far, and it's fairly hacked together, so if there's anything that can be improved, naturally, I'd be all for that.
`
Public Class Form1
Dim lblName As Object
Public colleges As String
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim colleges() As String = IO.File.ReadAllLines("Colleges.txt")
ListBoxCollege.Items.AddRange(colleges)
End Sub
Private Sub btnSearchGo_Click(sender As Object, e As EventArgs) Handles btnSearchGo.Click
Dim n As Integer, college As String
college = txtCollegeSearchUserInput.Text
n = Array.IndexOf(colleges(), college)
If n <> 1 Then
[[Needs to output into new listbox, preferably here]]
End If
End Sub
If there's anything else needed from VB, I can provide if necessary!
In your case you can do something like this
For i As Integer = 0 To ListBoxCollege.Items.Count -1
If ListBoxCollege.Items(i).ToString().IndexOf(college, StringComparison.OrdinalIgnoreCase) > -1 Then
findList.Items.Add(ListBoxCollege.Items(i))
End If
Next
The difference here - you calling IndexOf on array and I call it for each item in list. Therefore I return all matches, while you only the first one
This is little bit limited in search criteria. You could use regex as well for wild cards etc. Or you store your data (colleges) in System.Data.DataTable, and you would be able to run Sql Select queries on it almost like in database.

Will you please help me in my migration to VB.NET from VB 6.0? [duplicate]

This question already has answers here:
Control array in VB.NET
(3 answers)
Closed 8 years ago.
I just read a certain article about the control arrays of VB6 not present in VB.NET and rather, became a "collection" or something.... (http://visualbasic.about.com/od/usingvbnet/l/bldykctrlarraya.htm)
Now, I'm planning to learn VB.NET and accept it as whole new language.
So, as a "few steps" for me to migrate, here is my code from VB6:
Private Sub Command1_Click()
For i = 0 to 9
Command2(i).Caption = i
Next i
End Sub
Private Sub Command2_Click(Index as Integer)
Label1.Caption = Label1.Caption + Index
End Sub
I wonder if you get what my program is? Let's just say it's a certain number pad program. I'll explain what this program does, at least for now...
As you can see, I have 12... controls? (I'm sorry, I'm still a little bit new in terms of programming)... Yeh, 12 of them... 11 buttons and 1 Label. That 1 button, Command1, will give the captions of my other 10 buttons Command2(Index). And when Command2(Index) is pressed, Label1's current caption will be concatenated by Command2(Index)'s Index... (It's like a calculator, let's skip this now)
So, will you teach me a version/translation of this in VB.NET? :) Thanks!
Just Add 12 regular buttons onto your form Button1 - Button12
Then create a list to hold a reference to these:
Private _buttonList As New List(Of Button)
Add your buttons to the list on Form_Load:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
_buttonList.Add(Button1)
_buttonList.Add(Button2)
_buttonList.Add(Button3)
'etc.
End Sub
Then you can use the list to access your buttons by (zero based) index:
_buttonList(4).Text = "foo"

Resources