Progress bar gets stuck at 100% - vb.net

I've programmed a "Please wait" form in which I inserted a progress bar. I looked around how to program a progress bar and this is what I did. First of all I programmed the button - Button3_Click - I press to start. Then I programmed the timer - Timer1_Tick -and so I wrote:
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Timer1.Enabled = True
Timer1.Interval = 50
Timer1.Start()
*[calculus code]*
If Form18.ProgressBar1.Value = 100 Then
Form18.Hide()
hrrspkexcel.Visible = True
End If
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
iProgressBarValue += 1
Select Case iProgressBarValue
Case 1, 3, 5, 7, 9
Form18.ProgressBar1.ForeColor = Color.White
Form18.Label3.Text = Form18.ProgressBar1.Value & (" %")
Form18.ProgressBar1.Value = (iProgressBarValue * 10)
Case 2, 4, 6, 8
Form18.Label3.Text = Form18.ProgressBar1.Value & (" %")
Form18.ProgressBar1.Value = (iProgressBarValue * 10)
Case 10
Form18.ProgressBar1.Value = (iProgressBarValue * 10)
Form18.Label3.Text = Form18.ProgressBar1.Value & (" %")
Timer1.Stop()
Timer1.Enabled = False
End Select
End Sub
I can't understand why the progress bar gets stuck at 100% and neither form18 gets hidden, nor hrrspkexcel becomes visible. Where am I doing wrong? Thanks for any support. Best regards.
Edit: I tried to edit my code as comments say:
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Timer1.Enabled = True
Timer1.Interval = 50
Timer1.Start()
[calculus code]
iProgressBarValue += 1
Select Case iProgressBarValue
Case 1, 3, 5, 7, 9
Form18.ProgressBar1.ForeColor = Color.White
Form18.Label3.Text = Form18.ProgressBar1.Value & (" %")
Form18.ProgressBar1.Value = (iProgressBarValue * 10)
Case 2, 4, 6, 8
Form18.Label3.Text = Form18.ProgressBar1.Value & (" %")
Form18.ProgressBar1.Value = (iProgressBarValue * 10)
Case 10
Form18.ProgressBar1.Value = (iProgressBarValue * 10)
Form18.Label3.Text = Form18.ProgressBar1.Value & (" %")
Timer1.Stop()
Timer1.Enabled = False
End Select
If Form18.ProgressBar1.Value = 100 Then
Form18.Hide()
hrrspkexcel.Visible = True
End If
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
If Form18.ProgressBar1.Value = 100 Then
Timer1.Stop()
Timer1.Enabled = False
End If
End Sub
In this case, progress bar gets stuck at 10%.
Edit II: Following suggestions in comment, I removed the timer and based my progress bar on the entity of the calculus code (Form18.ProgressBar1.Maximum). Anyway, what is reported under [calculus code] is an heavy Excel export so the progress bar freezes to 0% until exportation has ended and then start running (I set loading cursor to understand when exportation has ended), so maybe I'd need of a BackgroundWorker to make my bar progressing while exporting? (I'm a beginner programmer and I read somewhere something about this, but I don't know if this solution is suitable for me, so I'm asking).
At last, this is how I corrected my code:
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Form18.ProgressBar1.Minimum = 0
Form18.ProgressBar1.Value = 0
Form18.ProgressBar1.Maximum = [if loop criteria based on my code]
Form18.ProgressBar1.Increment(1)
Form18.Show()
[calculus code - excel export]
If Form18.ProgressBar1.Value = Form18.ProgressBar1.Maximum Then
Form18.Hide()
hrrspkexcel.Visible = True
End If
End Sub
With this edit, my ProgressBar freezes at 0% even if exportation has already ended, so I'm obviously doing wrong somewhere. Thanks for all the support you're giving to me.
Edit III: I managed in making progressbar working using a for loop to increment its value, as you suggested me, with a proportional equation to percentage and to overcome the problem about the maximum value of the bar, that's always set on 100. So thanks all of you for your support. The last thing I want to ask you - if I'm not offtopic - is how to make my loading form - with the progressbar - on foreground and to "lock" interaction with all other forms.
Edit III BIS: I've tried to use Backgroundworker in order to overcome the loading-form freezing. This is the first time I'm using this command and I don't know if it's the right way to make it comunicating to a ShowDialog Form. This is what I wrote:
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
Form18.ProgressBar1.Minimum = 0
Form18.ProgressBar1.Value = 0
BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Form18.ShowDialog()
[excel calculus export]
If Form18.ProgressBar1.Value = Form18.ProgressBar1.Maximum Then
Form18.Hide()
hrrnativexcel.Visible = True
End If
End Sub
I'm always getting the same trouble: when Form18 appears, remains on 0% loading.
Edit IV: I'm having an issue about progressbar increment for the following situation: I have two for loops for exporting values in excel and the upper bound of this loops are different. So I've created a third for loop, whose upper bound is the sum of the upper bounds of the two abovementioned for loops, in order to increment the progressbar progress. When it reaches 100%, it starts again going in loop. How could I solve this issue? Here is the code I'm using:
For i = 1 To CInt(Form6.ListBox1.Items.Count)
For j = 1 To CInt(Form10.ListBox1.Items.Count)
For k = 0 To CInt(CInt(Form6.ListBox1.Items.Count) + CInt(Form10.ListBox1.Items.Count))
hrrspkexcel.Cells(j + 1, 1).value = Form10.ListBox2.Items(CInt(j + 1) - 2)
hrrspkexcel.Cells(i + 1, 2).value = Form6.ListBox1.Items(CInt(i + 1) - 2)
Form18.ProgressBar1.Value = CInt(100 * k / (CInt(Form6.Label9.Text) + CInt(Form10.ListBox1.Items.Count)))
Form18.Label3.Text = Form18.ProgressBar1.Value & (" %")
Next
Next
Next
Thanks in advance.
Edit V: I've updated my code following comments in order to solve the issue described in Edit IV. This is what I wrote:
Dim pbloop As Integer
pbloop = CInt(Form10.ListBox1.Items.Count) * CInt(Form6.ListBox1.Items.Count)
For p = 1 To pbloop
For i = 1 To CInt(Form6.ListBox1.Items.Count)
For j = 1 To CInt(Form10.ListBox1.Items.Count)
hrrspkexcel.Cells(i + 1, 4).value = Form6.ListBox1.Items(CInt(i + 1) - 2)
hrrspkexcel.Cells(i + 1, 3).value = Form6.ListBox2.Items(CInt(i + 1) - 2)
hrrspkexcel.Cells(j + 1, 1).value = Form10.ListBox1.Items(CInt(j + 1) - 2)
hrrspkexcel.Cells(j + 1, 2).value = Form10.ListBox2.Items(CInt(j + 1) - 2)
Form18.ProgressBar1.Value = CInt(100 * p / pbloop)
Form18.Label3.Text = Form18.ProgressBar1.Value & (" %")
Next
Next
I'm getting stuck always at 0% and progress bar that doesn't increase.

This is not the true answer of the problem but a sample to show you how to use a progress bar.
This code is not beautiful, I know, it's for the example. Please be careful when you use a textbox text as a number without check what is written.
Imports System.Threading
Public Class Form1
Private Sub btnGo_Click(sender As Object, e As EventArgs) Handles btnGo.Click
' Initialisation of the progressbar
myProgressbar.Value = 0
myProgressbar.Maximum = tbxTo.Text
lbxInfos.Items.Clear() ' Clear the content in the listbox1 if it's not the first run
' This simulate your [calculus code], I just add an information in the listbox
For i As Integer = tbxFrom.Text To tbxTo.Text
myProgressbar.Value = i ' Set the progressbar avancement
lbxInfos.Items.Add("This is the loop n° " & i & " !")
lbxInfos.Refresh() ' Just because the listbox will not be refresh until the end of the sub
Thread.Sleep(200) ' The code is too fast, I add this to see the progress (= wait 200 ms)
Next
MsgBox("This is the end ! Now the form will be closed")
Me.Close()
End Sub
End Class

Try something more like this out:
Private Async Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Button3.Enabled = False
hrrspkexcel.Visible = False ' changed this to a Label next to the button just for demonstration
Dim f18 As New Form18
f18.ProgressBar1.Minimum = 0
f18.ProgressBar1.Value = 0
f18.ProgressBar1.Maximum = 100 ' <-- leave the maximum at 100!
f18.Show(Me)
Dim pct As Integer
Dim maximum As Integer = 319 ' <-- figure out the max value based on your "calculus code"
Await Task.Run(Sub()
' [calculus code - excel export]
For i As Integer = 0 To maximum
System.Threading.Thread.Sleep(50) ' <- some kind of processing going on
' calculate the percentage based on your loop value "i" and the "maximum":
pct = CDbl(i) / CDbl(maximum) * 100 ' <-- scale your loop value to 100
Try
f18.ProgressBar1.Invoke(Sub()
f18.ProgressBar1.Value = pct
End Sub)
Catch ex As Exception
' User closed the progressform, create another one
Me.Invoke(Sub()
f18 = New Form18
f18.ProgressBar1.Minimum = 0
f18.ProgressBar1.Value = 0
f18.ProgressBar1.Maximum = 100 ' <-- leave it at 100
f18.Show(Me)
' make progressbar immediately jump to the right spot
f18.ProgressBar1.Value = f18.ProgressBar1.Maximum
f18.ProgressBar1.Value = pct
End Sub)
End Try
Next
End Sub)
' when we hit here, the "calculus code" above completed
f18.Close()
hrrspkexcel.Visible = True ' changed this to a Label next to the button just for demonstration
Button3.Enabled = True
End Sub
Here's what it looks like in action:

You current code reads as if you want the Progress Bar to update on a button click a maximum of 10 times before hiding the form. Is that your intention? I would have expected that you want the "Please wait ..." form to stay visible with the progress bar updating every, say, second, then disappear?
Using a timer for the latter is fine but for the former, you can simply update the progress bar directly - as you are doing - without a timer.
Also, you don't need to multiply your progress bar value by 10; you can simply set the progress bar Maximum value to 10.
Also, since you change the ForeColor value on the first click, you can probably dispense with the Case Select {even|odd} test because the code is otherwise identical.
So without the timer or the color change and with Progress Bar Maximum = 10, all you need to do is:
Form18.ProgressBar1.Value = iProgressBarValue
Form18.Label3.Text = $"{iProgressBarValue} %")
No need for the Case Select.
Another option for the PB is to use the PerformStep() method to increment it. Just set the Step property to 1 for this approach.

Related

Solved; See Edit5; Running a "For Each" Loop in Visual Basic "Space Invaders" Game seems to slowdown everything else

[Solved] See Edit5
I'm trying to make a "Space Invaders" game for a class and every time I turn on the timer handling the enemies the player movement slows down immensely. I'm almost sure the issue, or at least the bulk of it, comes from this loop:
For Each PicBox2 In EnemyList
If Not ((PicBox2.Left + EMovDir * ESpeed < 0) Or (PicBox2.Right + EMovDir * ESpeed >= Me.Width - 10)) Then
PicBox2.Location = New Point(PicBox2.Location.X + EMovDir * ESpeed, PicBox2.Location.Y)
If PicBox2.Bounds.IntersectsWith(Player.Bounds) Then GameOver = True
End If
Next
Here is a screenshot of the form design:
[enter image description here][1]
And here is the code I have so far:
Public Class Form1
Region Variables
Dim PSpeed As Integer = 5 'Pixeis de movimento do jogador por trigger do EventoKeyDown
Dim ESpeed As Integer = 10 'Pixeis de movimento dos inimigos por loop
Dim ENumber As Integer 'Número de inimigos
Dim PHealth As Integer 'Número de vezes que o jogador pode ser atingdo até GameOver
Dim PMoveStateL As Boolean
Dim PMoveStateR As Boolean
Dim GameOver As Boolean
Dim EMovDir As Integer = 1
Dim PicBox As PictureBox
Dim EnemyList As New List(Of PictureBox)
End Region
Region Game Load
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For Each PicBox In Me.Controls.OfType(Of PictureBox)
If PicBox.Tag = "Enemy" Then
EnemyList.Add(PicBox)
End If
Next
End Sub
End Region
Region InGame Ui
Private Sub StopStartTimer_Click(sender As Object, e As EventArgs) Handles Button3.Click
If EnemyTimer.Enabled = False Then
EnemyTimer.Enabled = True
Else EnemyTimer.Enabled = False
End If
End Sub
End Region
Region PlayerControls
Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown 'Não Esquecer de ativar a Propriedade KeyPreview
If e.KeyCode = Keys.D And (Player.Location.X + PSpeed) < (Me.Width - Player.Width) Then
PMoveStateR = True
End If
If e.KeyCode = Keys.A And ((Player.Location.X - PSpeed) > 0) Then
PMoveStateL = True
End If
End Sub
Private Sub Form1_KeyUp(sender As Object, e As KeyEventArgs) Handles Me.KeyUp
If e.KeyCode = Keys.D Then
PMoveStateR = False
End If
If e.KeyCode = Keys.A Then
PMoveStateL = False
End If
End Sub
Private Sub PlayerTimer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PlayerTimer.Tick
If PMoveStateR = True And (Player.Location.X + PSpeed) < (Me.Width - Player.Width) Then
Player.Location = New Point((Player.Location.X + PSpeed), Player.Location.Y)
End If
If PMoveStateL = True And ((Player.Location.X - PSpeed) > 0) Then
Player.Location = New Point((Player.Location.X - PSpeed), Player.Location.Y)
End If
End Sub
End Region
Region Enemy Behavior
Private Sub EnemyTimer_Tick(sender As Object, e As EventArgs) Handles EnemyTimer.Tick
For Each PicBox2 In EnemyList
If ((PicBox2.Left - ESpeed < 0) Or (PicBox2.Right + ESpeed >= Me.Width - 10)) Then
'Something I don't really understand seems to be going with the .Right reading where either it doesn't line up with the form width, or the form width doesn't line up with the form's zsize while running. The -10 pixels seem to offset it.
For Each PicBox3 As PictureBox In EnemyList
PicBox3.Location = New Point(PicBox3.Location.X, PicBox3.Location.Y + PicBox3.Height)
If PicBox.Bounds.IntersectsWith(Player.Bounds) Then GameOver = True
Next
End If
Next
For Each PicBox2 In EnemyList
If ((PicBox2.Left + EMovDir * ESpeed < 0) Or (PicBox2.Right + EMovDir * ESpeed >= Me.Width - 10)) Then
EMovDir = EMovDir * -1
End If
Next
For Each PicBox2 In EnemyList
If Not ((PicBox2.Left + EMovDir * ESpeed < 0) Or (PicBox2.Right + EMovDir * ESpeed >= Me.Width - 10)) Then
PicBox2.Location = New Point(PicBox2.Location.X + EMovDir * ESpeed, PicBox2.Location.Y)
If PicBox2.Bounds.IntersectsWith(Player.Bounds) Then GameOver = True
End If
Next
End Sub
End Region
End Class
The tutorial I was following used arrays instead of a list, but I thought I would try to code this in such a way that adding or removing enemies wouldn't require me to edit the code and learn how to along the way. I've already tried fixing everything that occurred to me could be the cause, which is how I've arrived at the code above. I really appreciate any help you can give in fixing this, as well as any advice, Thanks! (and sorry for my english)
Edit: I hadn't thought to make sure, but just confirmed the more "Enemy" picture boxes the worse the issue gets.
Edit2: Weird as it might sound I checked if maybe the slower player movement was an optical illusion due to the background and/or the aliens point of reference also being in movement. That was not it either.
Edit3: Running a third timer at a 1000 millisecond interval and displaying the number of seconds since the timer was enabled while checking against the stopwatch in my phone revealed that it's not that the entire form is slowing down. The issue is replicated regardless of any image size mode, or any other picturebox and timer property .
Edit4: If I stretch the form window while it's running so that the aliens aren't in view, the Player moves normally.
Edit5: [Solved] The issue only occurs if the form has a background image. I have absolutely no idea why .
It took me way too long to track down what was causing this bizarre issue, and it's bizarre properties.
Regardless, I would like to thank Idle_Mind and Hack_Slash for helping me improve my code and teaching me some cool new stuff.
The way you've got it written, EVERY time an enemy hits the left or right sides, all enemies will move down. But doesn't that mean they could all move down multiple times?...once for each time an enemy has hit the edge, which could be multiple enemies if they are in a column?
See if something more like this performs better:
Private Sub EnemyTimer_Tick(sender As Object, e As EventArgs) Handles EnemyTimer.Tick
Dim edgeWasHit = EnemyList.Any(Function(pb) (pb.Left - ESpeed < 0) OrElse (pb.Right + ESpeed >= Me.Width - 10))
Dim reverseDirection = EnemyList.Any(Function(pb) (pb.Left + EMovDir * ESpeed < 0) OrElse (pb.Right + EMovDir * ESpeed >= Me.Width - 10))
If reverseDirection Then
EMovDir = EMovDir * -1
End If
For Each PicBox2 In EnemyList
If edgeWasHit Then
' move it down
PicBox2.Location = New Point(PicBox2.Location.X, PicBox2.Location.Y + PicBox2.Height))
End If
' move left/right
PicBox2.Location = New Point(PicBox2.Location.X + EMovDir * ESpeed, PicBox2.Location.Y)
If PicBox2.Bounds.IntersectsWith(Player.Bounds) Then
GameOver = True
Exit Sub
End If
Next
End Sub

Background Thread slowing Main UI Thread visual basic [duplicate]

This question already has an answer here:
vb.net - service app & forms app both have very high CPU usage since adding socket comms
(1 answer)
Closed 2 years ago.
I would like to show a gif inside a Picture Box for 2 seconds on a separate thread from the main thread. I am running a timer that moves a Picture Box with an Image on the main thread.
To test I created a Picture Box and added same Image I start the background thread with a button click. The obvious ERROR or Issue is that the supposed Background Thread slows the Main Thread.
Creating and Implementing a Threads seems to offer two options BackgroundWorker and Task.Run.
I looked at this Code Magazine Article which offered way more options than I am grasping: Code Magazine Article
Also looked at this Article could not convert the C# code to VB YES I used a code converter: Stephen Cleary
My code is posted below for the Background Thread No need to post the Timer Tick Code.
Question what am I missing or what am I doing wrong OR is this just not possible?
Private Sub myThreadMethod()
'Await
'Async
Dim myThread As New Thread(AddressOf myThreadMethod)
myThread.IsBackground = True
myThread.Start()
If Me.InvokeRequired = True Then
Me.Invoke(Sub()
'PbT.Location = New Point(128, 132)
PbT.Left -= 1
PbT.Top += 2
End Sub)
'If PbT.Bounds.IntersectsWith(btnBot.Bounds) Then
'TextBox1.Invoke(Sub() TextBox1.Text =
End If
If PbT.Location.Y > 500 Then
PbT.Invoke(Sub() PbT.Location = New Point(350, 230))
Thread.Sleep(9000)
myThread.Abort()
End If
End Sub
Answer to Question was added to by Craig and Answered by James_Duh
Public Class frmStart
Dim running As Boolean = False
Dim stopWatch As Stopwatch = New Stopwatch
Private Sub frmStart_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
Cursor.Clip = New Rectangle(Me.Location, Me.Size)
btnLPad.Left = e.X
btnCPad.Left = e.X + 28
btnRPad.Left = e.X + 56
End Sub
Private Sub tmrMove_Tick(sender As Object, e As EventArgs) Handles tmrMove.Tick
Static direction As New Point(0, 4)
Static endTime As DateTime = DateTime.Now.AddYears(1)
If DateTime.Now > endTime Then
PbT.Visible = False
endTime = DateTime.Now.AddYears(1)
End If
If _buttons.All(Function(x) x.Button.Visible = False) Then
pbOne.Top = 300
PbT.Visible = False
tbAns.Visible = True
stopWatch.Stop()
Dim ts = stopWatch.Elapsed
Dim elapsedTime = $"{ts.Minutes:0} Min {ts.Seconds:00} Sec"
tbAns.Text = elapsedTime
running = False
direction = New Point(0, 4)
tmrMove.Stop()
MsgBox("You Win")
stopWatch.Reset()
'================
tbAns.Visible = False
ResetButtons()
End If
If pbOne.Bounds.IntersectsWith(btnLPad.Bounds) Then
direction = New Point(-2, -3)
End If
If pbOne.Bounds.IntersectsWith(btnRight.Bounds) Then
Static spC As Integer = 1
spC += 1
direction = If(spC Mod 2 = 0, New Point(-3, 2), New Point(-5, 1))
End If
If pbOne.Bounds.IntersectsWith(btnLeft.Bounds) Then
direction = New Point(4, 2)
End If
If pbOne.Bounds.IntersectsWith(btnCPad.Bounds) Then
direction = New Point(direction.X, -4)
End If
If pbOne.Bounds.IntersectsWith(btnRPad.Bounds) Then
Static spA As Integer = 1
spA += 1
direction = If(spA Mod 2 = 0, New Point(1, -5), New Point(-3, -4))
End If
If pbOne.Bounds.IntersectsWith(btnTop.Bounds) Then
Static spE As Integer = 1
spE += 1
direction = If(spE Mod 2 = 0, New Point(-3, 2), New Point(4, 2))
End If
If pbOne.Bounds.IntersectsWith(btnBot.Bounds) Then
tmrMove.Stop()
running = False
pbOne.Top = 200
PbT.Visible = False
MsgBox("Press S to Start")
End If
pbOne.Left += direction.X
pbOne.Top += direction.Y
For Each x In _buttons
If pbOne.Bounds.IntersectsWith(x.Button.Bounds) Then
endTime = DateTime.Now.AddSeconds(2.0)
x.Button.Visible = False
x.Button.Location = New Point(350, -30)
PbT.Location = New Point(x.Location.X + 20, 31)
PbT.Visible = True
direction = New Point(3, 3)
End If
Next
End Sub
Private Sub frmStart_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
If running AndAlso e.KeyCode = Keys.P Then
tmrMove.Stop()
End If
If e.KeyCode = Keys.S Then
If Not running Then
stopWatch.Start()
running = True
End If
tmrMove.Interval = 1
tmrMove.Start()
End If
End Sub
Public Sub frmStart_KeyPress(sender As Object, e As KeyPressEventArgs) Handles Me.KeyPress
'Form Property KeyPreview needs to be set to True
'=================================================
If Asc(e.KeyChar) = 27 Then
Const message As String = "YES" & " Exit Program" + vbCrLf + vbNewLine + "NO" & " Read Directions"
Const caption As String = "Exit OR Return"
Dim result = MessageBox.Show(message, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If result = DialogResult.Yes Then
Application.Exit()
ElseIf result = DialogResult.No Then
frmInfo.Show()
Close()
End If
End If
End Sub
Private _buttons As (Button As Button, Location As Point)() = Nothing
Private Sub frmStart_Load(sender As Object, e As EventArgs) Handles MyBase.Load
If _buttons Is Nothing Then
_buttons =
{
(btnB1, New Point(29, 32)),
(btnB2, New Point(110, 32)),
(btnB3, New Point(191, 32)),
(btnB4, New Point(272, 32)),
(btnB5, New Point(353, 32)),
(btnB6, New Point(434, 32)),
(btnB7, New Point(515, 32)),
(btnB8, New Point(596, 32)),
(btnB9, New Point(677, 32))
}
End If
ResetButtons()
End Sub
Private Sub ResetButtons()
For Each x In _buttons
x.Button.Visible = True
x.Button.Location = x.Location
Next
End Sub
End Class
This Code above was from Enigmativity and FIXES a number of issues. See his comments about the Stopwatch and playing the gif. As well the game plays 70% Faster with his code
Trying to reproduce this NOT seeing your Timer tick code I wrote my own
Understanding the GAME design of Breakout will help for anyone trying to follow Vectors steps need to show the gif for X amount of Seconds
First you need to Stopwatch integrated into the Timer
Second you need to know when to set the END time in Seconds Logic would require this happens when the BALL IntersectsWith the BRICK
So we write a Function called Fire see code below
NO need to have a gif for each BRICK so now we need to move our one and only gif to the correct BRICK and let it run for X Seconds We also need to make the gif Visible WHY you might ask if Enabled and Visible they run for ever It was easier to just manage Visibility
You also need code inside the Timer Tick method to make the gif Invisible after X Seconds
Excuse my lack of declarative variables
pbOne = the BALL & btnB1 = BRICK & PbT = Picture Box with the gif
Public Function Fire() As Integer
'Set Stopwatch 5 sec in the future
nT = CDbl(DateTime.Now.AddSeconds(5).ToString("ss"))
Return CInt(nT)
End Function
Private Sub tmrMove_Tick(sender As Object, e As EventArgs) Handles tmrMove.Tick
'nS is Rolling Time
nS = CDbl(DateTime.Now.ToString("ss"))
If nS > nT Then
PbT.Visible = False
End If
If pbOne.Bounds.IntersectsWith(btnB1.Bounds) Then
btnB1.BackColor = Color.Red
btnB1.Visible = False
Fire()
Y = btnB1.Location.Y
X = btnB1.Location.X
PbT.Location = New Point(X + 20, Y)
PbT.Visible = True
btnB1.Location = New Point(350, -30)
rndNUM = 8
End If

How to show dgv2 right beneath the row in dgv1 being edited

I am trying to show a dgv2 on dgv1 but right under the row in dgv1 being edited.
I tried with this code
Private Sub Purchases_CellBeginEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellCancelEventArgs) Handles Purchases.CellBeginEdit
Dim Y as integer = 0
For i As Integer = 0 To dgv1.CurrentRow.Index
If dgv1.Rows(i).Index < dgv1.CurrentRow.Index Then
Y = dgv1.Rows.Count * dgv1.Rows(0).Height + dgv1.ColumnHeadersHeight + 12
End If
Next
dgv2.Location = New Point(53, Y)
End Sub
I shows alright but when i go back to row 1 on dgv1, it stays where it is. Lets say i start to edit from row 1 and i get to row 4, and i want to make a correction in row 1, i want dgv2 to move back under row1.
Any help would be greatly appreciated.
Just ran into this myself and found using the mouse y position (minus top of the form + 24) worked perfect.
Private Sub DataGridView1_CellEnter(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellEnter
mouseY = Windows.Forms.Cursor.Position.Y - Me.Top + 24
End Sub
I removed the if condition and it works perfectly
this is the code
Try
For i As Integer = 0 To Purchases.CurrentRow.Index
Y = i * Purchases.Rows(0).Height + Purchases.ColumnHeadersHeight + 34
Next
itemlist.Location = New Point(53, Y)
Catch ex As Exception
MsgBox(ex.Message)
End Try

Nested timers? Trouble with logic on multiple simultaneous timer ticks

I'm trying to create a simple visual example and the first step is having a column of boxes (panels) move across the screen. So far I've accomplished that, but I'm also attempting to have each panel blink a few times, individually, while moving. The effect should be a type of 'round robin' loop where the first panel blinks a few times, then the second, then the third, etc, etc and repeat.
I'm quite new to VB and so far I've only been able to successfully make either only one panel blink or all of the panels blink, not each one individually. Here's my code so far:
Public Class Form1
Public ticks As Integer
Public p(4) As Panel
Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
p(0) = Panel1
p(1) = Panel2
p(2) = Panel3
p(3) = Panel4
p(4) = Panel5
ticks = 0
End Sub
Private Sub tmr1_Tick(sender As Object, e As System.EventArgs) Handles tmr1.Tick
Dim i As Integer
If ticks = 1 Then
For i = 0 To 4
Dim randomValue = Rnd()
p(i).Top = 50 + 75 * i
p(i).Left = randomValue * 120
Next
ElseIf ticks > 30 Then
ticks = 0
Else
For i = 0 To 4
p(i).Left += 20
Next
End If
ticks += 1
End Sub
Private Sub tmr2_Tick(sender As System.Object, e As System.EventArgs) Handles tmr2.Tick
Dim i As Integer
For i = 0 To 4 'all of the panels blink at the same time..
If p(i).Visible = False Then
p(i).Visible = True
ElseIf p(i).Visible = True Then
p(i).Visible = False
End If
Next
End Sub
End Class
As of right now, all of the panels blink while moving across the screen in random locations, I'm assuming this is because the for loop responsible for the blinking is nested within the ticking timer, so for each tick it runs through the loop fully.
I'm a little stumped on what should be some very simple logic, but please bear with me as I am a novice.
Thank you for any and all help!
If I understand what you want, this would do it. They all blink now because they are all in the loop that occurs with each tick, this example changes each one by it's index in the array, and the index variable must be class level to retain it's value between ticks.
Private index As Integer
Private Sub tmr2_Tick(sender As System.Object, e As System.EventArgs) Handles tmr2.Tick
p(index).Visible = Not p(index).Visible
If index = 4 Then
index = 0
Else
index += 1
End If
End Sub

VB.NET: Image as checkbox state box

Is it possible to use an image as the checkbox "checked" indicator square?
I know I can use a background image, but that goes behind the label aswell and also it is not possible (as far as I know) to align it.
How can I use an image instead of the square and leave the label and all other customization as they are?
Thanks in advance!
You look like this?
Dim frm As New Form
frm.Size = New Size(320, 200)
Dim iList As New ImageList
iList.Images.Add(Image.FromFile("check.png"), Color.White)
iList.Images.Add(Image.FromFile("uncheck.png"), Color.White)
Dim chk As New CheckBox
chk.Text = "Check Box With Image"
chk.AutoSize = False
chk.Size = New Size(350, 20)
chk.ImageList = iList
chk.ImageIndex = 1
chk.CheckAlign = ContentAlignment.MiddleRight
chk.ImageAlign = ContentAlignment.MiddleLeft
chk.TextImageRelation = TextImageRelation.ImageBeforeText
chk.Location = New Point(32, 32)
frm.Controls.Add(chk)
AddHandler chk.CheckStateChanged,
Sub(sender1 As Object, e1 As EventArgs)
chk.ImageIndex = IIf(chk.Checked, 0, 1)
End Sub
frm.ShowDialog()
UPDATE #1: Actually, #brahm solution's below is much better than mine!
UPDATE #2: Actually, it's not. Now I see how he did it: he's moving the checkbox out of sight by placing it way off the visible Form's area. Not a great solution...
The ideal solution would be to subclass the CheckBox control and do your own rendering by overriding the OnPaint method.
An easier, although probably messier solution, would be to place a PictureBox over the check box and control the image in the PictureBox through the CheckBox's CheckedChange event.
Another option:
You could still use the CheckBox in button mode (Appearance = Button), as you suggested, but then add a label right next to it.
Then, handle the Click event on the Label to toggle the Checked state of the CheckBox. Then end result should provide you exactly what you are looking for.
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Windows.Forms.VisualStyles
Public Class ImageCheckBox
Public State As CheckBoxState = CheckBoxState.UncheckedNormal
Public Hot As Boolean = False
Public Pressed As Boolean = False
Public ImageDictionary As Dictionary(Of CheckBoxState, Image) = New Dictionary(Of CheckBoxState, Image)
Private Const PaddingModifier As Integer = 2
Sub New()
Me.New(New Dictionary(Of CheckBoxState, Image) From {
{CheckBoxState.CheckedDisabled, My.Resources.form_checkbox_checked},
{CheckBoxState.CheckedHot, My.Resources.form_checkbox_checked},
{CheckBoxState.CheckedNormal, My.Resources.form_checkbox_checked},
{CheckBoxState.CheckedPressed, My.Resources.form_checkbox_checked},
{CheckBoxState.UncheckedDisabled, My.Resources.form_checkbox_unchecked},
{CheckBoxState.UncheckedHot, My.Resources.form_checkbox_unchecked},
{CheckBoxState.UncheckedNormal, My.Resources.form_checkbox_unchecked},
{CheckBoxState.UncheckedPressed, My.Resources.form_checkbox_unchecked}})
End Sub
Sub New(imageDictionary As Dictionary(Of CheckBoxState, Image))
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Me.ImageDictionary = imageDictionary
End Sub
Sub CheckBox_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
'Return if the specific Image is not found
If Not ImageDictionary.ContainsKey(State) Then Return
'Get the Size of the CheckBox
Dim glyphSize As Size = CheckBoxRenderer.GetGlyphSize(e.Graphics, State)
'Get the Location of the CheckBox in relation to the Alignment of it
Dim glyphLocation As Point
Select Case Me.CheckAlign
Case Drawing.ContentAlignment.TopLeft
glyphLocation = New Point(Me.Padding.Left, Me.Padding.Top)
Exit Select
Case Drawing.ContentAlignment.TopCenter
glyphLocation = New Point(Me.Padding.Left + (Me.Width - glyphSize.Width) / 2, Me.Padding.Top)
Exit Select
Case Drawing.ContentAlignment.TopRight
glyphLocation = New Point(Me.Padding.Left + Me.Width - glyphSize.Width, Me.Padding.Top)
Exit Select
Case Drawing.ContentAlignment.MiddleLeft
glyphLocation = New Point(Me.Padding.Left, Me.Padding.Top + (Me.Height - glyphSize.Height) / 2)
Exit Select
Case Drawing.ContentAlignment.MiddleCenter
glyphLocation = New Point(Me.Padding.Left + (Me.Width - glyphSize.Width) / 2, Me.Padding.Top + (Me.Height - glyphSize.Height) / 2)
Exit Select
Case Drawing.ContentAlignment.MiddleRight
glyphLocation = New Point(Me.Padding.Left + Me.Width - glyphSize.Width, Me.Padding.Top + (Me.Height - glyphSize.Height) / 2)
Exit Select
Case Drawing.ContentAlignment.BottomLeft
glyphLocation = New Point(Me.Padding.Left, Me.Padding.Top + Me.Height - glyphSize.Height)
Exit Select
Case Drawing.ContentAlignment.BottomCenter
glyphLocation = New Point(Me.Padding.Left + (Me.Width - glyphSize.Width) / 2, Me.Padding.Top + Me.Height - glyphSize.Height)
Exit Select
Case Drawing.ContentAlignment.BottomRight
glyphLocation = New Point(Me.Padding.Left + Me.Width - glyphSize.Width, Me.Padding.Top + Me.Height - glyphSize.Height)
Exit Select
End Select
'Set the drawing Area
Dim glyphRectangle As Rectangle = New Rectangle(glyphLocation, glyphSize)
'Enlarge the Rectangle to completely hide default symbol
Dim clearRectangle As Rectangle = New Rectangle(glyphLocation.X - PaddingModifier,
glyphLocation.Y - PaddingModifier,
glyphSize.Width + 2 * PaddingModifier,
glyphSize.Height + 2 * PaddingModifier)
'Draw the Parent Background over the default CheckBox to clear it
CheckBoxRenderer.DrawParentBackground(e.Graphics, clearRectangle, Me)
Debug.WriteLine(State)
'Finally draw the custom CheckBox image on the position of the default one
e.Graphics.DrawImage(ImageDictionary(State), glyphRectangle)
End Sub
Sub CheckBox_MouseClick(sender As Object, e As EventArgs) Handles Me.MouseClick
Me.Checked = Not Me.Checked
End Sub
Sub CheckBox_MouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown
Me.Pressed = True
End Sub
Sub CheckBox_MouseUp(sender As Object, e As MouseEventArgs) Handles Me.MouseUp
Me.Pressed = False
End Sub
Sub CheckBox_MouseEnter(sender As Object, e As EventArgs) Handles Me.MouseEnter
Me.Hot = True
End Sub
Sub CheckBox_MouseLeave(sender As Object, e As EventArgs) Handles Me.MouseLeave
Me.Hot = False
End Sub
Public Sub updateState() Handles Me.MouseClick, Me.MouseDown, Me.MouseUp, Me.MouseEnter, Me.MouseLeave, Me.EnabledChanged
Debug.WriteLine(Me.Checked & " " & Me.Enabled & " " & Me.Hot & " " & Me.Pressed)
Me.State = CurrentState()
Me.Refresh()
Debug.WriteLine(State)
End Sub
Public Function CurrentState() As CheckBoxState
If (Me.Checked) Then
If (Not Me.Enabled) Then Return CheckBoxState.CheckedDisabled
If (Me.Pressed) Then Return CheckBoxState.CheckedPressed
If (Me.Hot) Then Return CheckBoxState.CheckedHot
Return CheckBoxState.CheckedNormal
Else
If (Not Me.Enabled) Then Return CheckBoxState.UncheckedDisabled
If (Me.Pressed) Then Return CheckBoxState.UncheckedPressed
If (Me.Hot) Then Return CheckBoxState.UncheckedHot
Return CheckBoxState.UncheckedNormal
End If
End Function
End Class
I also had this problem with a mute/unmute audiotrack i first went for the CheckBox but deceided to just use the PictureBox click event and used .location to get the New Point overlay the other PictureBox and enable the visibility of the one or the other box, works fine for a complete newb that i am :-)
Picture of the PictureBox in the Designer
Private Sub PictureBoxMute_Click(sender As Object, e As EventArgs) Handles PictureBoxMute.Click
PictureBoxMute.Visible = False
PictureBoxUnmute.Location = New Point(590, 433)
PictureBoxUnmute.Visible = True
Volume = 0
myplayer.Volume = Volume
End Sub
Private Sub PictureBoxUnmute_Click(sender As Object, e As EventArgs) Handles PictureBoxUnmute.Click
PictureBoxUnmute.Visible = False
PictureBoxMute.Visible = True
Volume = 1
myplayer.Volume = Volume
End Sub