Space out multiple dynamically created usercontrols - vb.net

So what im trying to do is create multiple instances of my usercontrol
Though I'm stuck on finding a way for them to be next to eachother like have a 5 pixel space between the next one created.

One way is to have a function that dynamically calculates it. I haven't tested this, but it should work. You just call doGetAppXPosition which loops thru all instances of your control and takes the last one found as the next x-position.
Dim App As New AppTab()
With App
...
.Location = New Point(doGetAppXPosition, 5)
...
End With
Me.Controls.Add(App)
Private Function doGetAppXPosition() as Integer
Dim xpos as Integer = 5
For Each oControl As Control In YourForm.Controls
If TypeOf oControl Is AppTab Then
xpos = oControl.Right + 5
End If
Next
Return xpos
End Function

Related

Loading up to 32768 Pictureboxes in Visual Basic

I have a app which is loading between 32^2 to 32768 8x8 px pictureboxes. All pictureboxes are on screen so I need to load them all and can't just load some.
As it stands, my program won't even run. Is there a better way to load that many pictureboxes?
I would like to share with you my project, but I don't know how to.............
Thanks though!
You'd likely run into a MemoryOverflowException with this design. From the sound of it, you're probably trying to render a map of some sort if that's the case then this answer is for you (otherwise just ignore it).
At a high level you should only create the number of PictureBox controls that can fit on the screen at any given time. You can calculate this with the following function:
Private Function CalculateSizeToFitParent(ByVal parent As Control, ByVal childSize As Size) As Size
Return New Size(parent.Width \ childSize.Width, parent.Height \ childSize.Height)
End Sub
You would implement it as such to create a PictureBox to fill up the visible area of the current Form:
Dim pictureBoxSize As Size = New Size(8, 8)
Dim visibleArea(pictureBoxSize.Width - 1, pictureBoxSize.Height - 1) As PictureBox
Dim numberOfPictureBoxes As Size = CalculateSizeToFitParent(Me, pictureBoxSize)
For x As Integer = 0 To numberOfPictureBoxes.Width - 1
For y As Integer = 0 To numberOfPictureBoxes.Height - 1
visibleArea(x, y) = New PictureBox() With {
.Location = New Point(x * pictureBoxSize.Width, y * pictureBoxSize.Height)
.Size = pictureBoxSize
}
Me.Controls.Add(visibleArea(x, y))
Next
Next
The next part is two-fold:
You need to keep track of where the top-left corner of the current visible are is
You will need to reload the images in the respective visual area of the map.
This assumes that you have a 2D array that stores your images. And please note that you don't recreate the PictureBox controls but rather you just reload the image of the existing control:
Private _currentLocation As Point = New Point(0, 0) ' If you're starting somewhere else change it here
Public Property CurrentLocation As Point
Get
Return _currentLocation
End Get
Set(ByVal value As Point)
If (value <> _currentLocation) Then
_currentLocation = value
Me.OnCurrentLocationChanged()
End If
End Set
End Property
Protected Overridable Sub OnCurrentLocationChanged()
RaiseEvent CurrentLocationChanged(Me, EventArgs.Empty)
End Sub
Public Event CurrentLocationChanged(ByVal sender As Object, ByVal e As EventArgs)
Private Sub MyForm_CurrentLocationChanged(ByVal sender As Object, ByVal e As EventArgs) Handles Me.CurrentLocationChanged
If (visibleArea Is Nothing) Then
Throw New Exception("The visible area has not been generated yet.")
End If
If (_currentLocation Is Nothing) Then
Throw New Exception("The CurrentLocation cannot be null.")
End If
Dim widthUpperBounds As Integer = My2DArrayOfImageLocations.GetUpperBounds(0) - 1
Dim heightUpperBounds As Integer = My2DArrayOfImageLocations.GetUpperBounds(1) - 1
For x As Integer = 0 To visibleArea.GetUpperBounds(0) - 1
For y As Integer = 0 To visibleArea.GetUpperBounds(1) - 1
If (x + _currentLocation.Width > widthUpperBounds OrElse y + _currentLocation.Height) Then
'This "block" is outside the view area (display a blank tile?)
Else
visibleArea(x, y).Load(My2DArrayOfImageLocations(x + _currentLocation.Width, y + _currentLocation.Height))
End If
Next
Next
End Sub
Now whenever you reset the CurrentLocation property (however you'd do that, e.g. arrow keys, asdw, etc.) it will redraw the visible area of the map.
Update
Please note that I "free-typed" this example and you may need to tweak it a bit. After some more thought, you'll probably also need to call the Refresh method of the PictureBox when you load in the image (I didn't test).

Dynamic UserControl Not Showing - flowlayoutpanel

I've array of items and for each item, creating a new instance of custom user control. The problem is that when the control is created and added to Flowlayoutpanel, it's not showing up.
Code
Sub createList()
Dim len_ids As Integer = account_ids.Length - 1
Dim x As Integer = 1
While x <= len_ids
Dim listItem As New wrapperItems()
listItem.txtName.Text = account_names(x)
listItem.picIcon.BackgroundImage = Image.FromFile(account_icons(x))
listItem.lblPath.Text = account_paths(x)
listItem.Tag = "listItem" & x
listItem.Top = 10 * x
listItem.Left = 10
Me.flowWrapper1.Controls.Add(listItem)
listItem.Show() ' tried this
listItem.Visible = True 'tried this
listItem.BringToFront() ' tried this
x += 1
End While
Me.Refresh()
End Sub
Anyone has idea of why it's not working?
It seems that when the background worker is started on Form.Show instead of Form.Load, the code doesn't work.
For the fix, I added background worker to Form.Load().
The better way was finally to add a refresh list button and then load the background worker.

VB.Net Hangman Game Multiple Rounds

I need some help.
I'm currently creating a Hangman Game in VB.Net.
I'm at the stage where a random word is loaded in from a text file of 6 words, and you can click buttons to guess it. If you guess letters wrong, the frame is shown etc, if they're right, the letter shows in the word through labels.
The next bit, that I'm stuck on, is that multiple rounds are needed. I need there to be 3 turns of this hangman game, so, if you guess the word right you get 10 points, and if you fail, you get 0, And then the game resets with your points and you can play again in Turn 2. Then again in Turn 3, and after Turn 3 finishes, the High Score Form is loaded.
You could create a variable to hold the current round in your Module, at the beginning of each round increase it, and at the end of the round check the current round and make a if then logic.
Dim myRound as Integer = 0
And in the PlayForm in the constructor.
myRound += 1
Once the round is complete.
if myRound >= 3 Then
'open the score page
Else
'start the next round
End if
'In General Declarations:
Dim ButtonList As New List(Of Button) 'or Of Control if you have other types of controls
Dim HgmList As New List(Of PowerPacks.Shape)
Dim AnswerList As New List(Of Label)
'In PlayForm_Load:
With ButtonList
.Clear()
.Add(Me.BtnA)
.Add(Me.BtnB)
.Add(Me.BtnC)
'You get the idea
'Add all your buttons you want to re-enable to the list
End With
With HgmList
.Clear()
.Add(Me.SideFrameLine)
.Add(Me.TopFrameLine)
.Add(Me.CornerFrameLine)
'etc.
End With
With AnswerList
.Add(Me.FirstLetterLbl)
'etc. Just like the other two.
End With
'At the end of your `If Correct = False Then` Block:
Else 'Check for win after each correct guess
Dim Winner As Boolean = True
Dim CheckLetter As Label
For Each CheckLetter in AnswerList
If Not CheckLetter.Visible Then
Winner = False
Exit For
End If
Next
If Winner Then
NextRound(10)
End If
End If
'Somewhere inside your form code:
Private Sub NextRound(RoundScore As Integer)
UserScore += RoundScore
If TurnNumber = 3 Then 'Game Over
MsgBox("Game Over" & vbNewLine & "Score: " & UserScore)
Else 'This is the part you asked about: resetting the form
TurnNumber += 1
PlayForm_Load(Nothing, Nothing)
Dim ResetControl As Control
Dim ResetShape As PowerPacks.Shape
For Each ResetControl In ButtonList
ResetControl.Enabled = True
Next
For Each ResetShape In HgmList
ResetControl.Visible = False
Next
End If
End Sub
I only added the .Clear() to the list builders because you already have your code to get a new word in PlayForm_Load. If you move it (say to a new Sub called NewWord), you don't need .Clear, and you would call your new sub instead of PlayForm_Load.

Referencing a picturebox using a variable image in Visual Basic 2012

I'm trying to modify an answer found here but I'm not having much luck....
What I'm trying to do is:
I have 12 pictures and 12 pictureboxes.
In a loop I'm trying to get it to check for the number and load the corresponding image(s)
so if it's #3 it should load images 1-3 in pictureboxes 1-3
I think I'm close but i can't figure it out
Declaration of Dictionary and passing subroutine
Dim ctrlDict As New Dictionary(Of Image, Control)
Dictionary(ctrlDict)
Definition Sub
Sub dicti(pictures() As Image, ByRef ctrlDict As Dictionary(Of Image, Control))
ctrlDict.Add(pictures(0), PictureBox1)
ctrlDict.Add(pictures(1), PictureBox2)
ctrlDict.Add(pictures(3), PictureBox3)
End Sub
Loop
The error I'm getting is "programname.my.resources is a namespace and cannot be used as an expression" and "picturebox is a type and cannot be used as an expression"
Sub Output(Days() As String, Prices() As String, WhichDay As String, total As Double, ctrlDict As Dictionary(Of Image, Control))
For i As Integer = 0 To 11
If WhichDay >= i Then
ctrlDict(PictureBox & i).Image = pictures(i)
End If
Next
End Sub
Off the top of my head, Pretty sure you cant do
ctrlDict(PictureBox & i).Image = pictures(i)
youll need to find the control that has the name property equal to (PictureBox.name & i). Then use that control and set the image.
Dont have an IDE on this computer but it will be something like
dim controlToUse as PictureBox
for each ctrl in ctrlDict
if ctrl.value.name = "Whatever youre calling your pictureboxes" & i then
controlToUse = ctrl.value
exit for
end if
next
if not controlToUse is nothing then controlToUse.image = pictures(i)
Please note that the above is psuedocode. Do not expect it to compile!
I found the answer
Dim pic As PictureBox
For i As Integer = 0 To 11
If WhichDay >= i Then
pic = Me.Controls("picturebox" & i + 1)
pic.Image = pictures(i)
End If
Next

How do I change the label back color (there are many labels) from dice roll results?

Hopefully this will make sense, but I am creating this 'board' type game where there is a die and twenty-eight labels, which I have made the labels into small squares and next to each other.
I need to figure out code which will automatically light up (change the BackColor) of the labels, based on the number generated by the die, which the player clicks on.
For example, when the player clicks the die a number is generated (1 - 6) and this is how many labels light up, and continues till all labels BackColor has changed to a different colour, e.g. green.
Code for die:
Private Sub imgDie_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles imgDie.Click
My.Computer.Audio.Play(My.Resources.Dice, AudioPlayMode.Background)
randomNumber = rand.Next(1, 7)
If randomNumber = 1 Then
imgDie.Image = My.Resources.Die_One
ElseIf randomNumber = 2 Then
imgDie.Image = My.Resources.Die_Two
ElseIf randomNumber = 3 Then
imgDie.Image = My.Resources.Die_Three
ElseIf randomNumber = 4 Then
imgDie.Image = My.Resources.Die_Four
ElseIf randomNumber = 5 Then
imgDie.Image = My.Resources.Die_Five
ElseIf randomNumber = 6 Then
imgDie.Image = My.Resources.Die_Six
End If
End Sub
So, what could I do to make sure the correct number of labels BackColor are changed? Would I need a function? Also, as the die is clicked numerous amount of times, labels are going to light up, so how do I get it so that those that haven't changed, are until all twenty-eight labels BackColor has changed?
I hope that this makes some sense?
The labels are named:
lblSquareOne, lblSquareTwo, lblSquareThree right through to lblSquareTwentyeight
Something like this might get you started:
Private Function ToggleLabels(ByVal NumberToDo As Integer) As Boolean
Dim R As New Random
Dim n As Integer
Dim count As Integer = 0
Dim lbl As Label
' in MY app, the labels would all be grouped (ALONE) on a panel
' so I could find them easily in its Controls Array
' I am also using the Label.Tag property to track it's state
' could also go by its BackColor
' do until we match the die count passed OR
' the new AllLitUp function tells us we are Done
Do Until (count = NumberToDo)
n = R.Next(0, 28) ' maxValue is exclusive
lbl = LabelsPanel.Controls(n)
' is this one already Lit?
If lbl.Tag = "FALSE" Then
' change the color
lbl.BackColor = TheLitColor
lbl.Tag = "TRUE" ' set indicator
count += 1 ' increase the count for this round
' dont need this here AND in the loop control
If AllLitUp() Then ' check for game over
Exit Do
End If
End If
Loop
' Return T/F is it Game Over
Return AllLitUp()
End Function
When you loop thru the labels to reset the color for a new game, be sure to set .Tag to "FALSE" (with the quotes).
Better would be LabelItem class which holds a reference to a label (which it could get itself when New) and a flag.
Then another class - LabelItems - to manage them. LabelItems could store 28 of them in a List(Of LabelItem). This would make managing individual labels easy (no need to loop thru an array) as well as 'global' things like a procedures to clear for a new game, get the score so far, add a Timer either for scoring or for Beat The Clock etc.