How to repeat a timer that ends with a message box? - vb.net

The purpose of the program is to remind the user to take a break every 30 minutes. The timer also allows the user to input how often to remind them. The countdown works only once when it reaches zero, however, l want to repeat the process three times. Dice images are placeholders. Sorry for any rookie errors.
Here is the code:
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
If lblHrs.Text = "0" And lblMin.Text = "0" And lblSec.Text = "0" Then
dice1 = Int(Rnd() * 6 + 1)
Select Case dice1
Case "1"
DiceRoll1.Image = My.Resources._1
Case "2"
DiceRoll1.Image = My.Resources._2
Case "3"
DiceRoll1.Image = My.Resources._3
Case "4"
DiceRoll1.Image = My.Resources._4
Case "5"
DiceRoll1.Image = My.Resources._5
Case "6"
DiceRoll1.Image = My.Resources._6
End Select
Timer1.Enabled = False
End If
Dim seconds As Double
Dim minutes As Double
Dim hours As Double
Double.TryParse(lblSec.Text, seconds)
Double.TryParse(lblMin.Text, minutes)
Double.TryParse(lblHrs.Text, hours)
If seconds = 0 And minutes <> 0 Then
lblSec.Text = 59
lblMin.Text = minutes - 1
ElseIf seconds > 0 Then
lblSec.Text = seconds - 1
End If
If minutes = 0 And hours <> 0 Then
lblMin.Text = 59
lblHrs.Text = hours - 1
End If
Dim Msg, Style, Title
Msg = "Time to rest and exercise." ' Define message.
Style = vbOKOnly + vbInformation ' Define buttons.
Title = "Rest reminder" ' Define title.
' Display message.
MsgBox(Msg, Style, Title)
End Sub

This is not a full answer to your question but I wanted to post a chunk of code so a comment was not a good option. This class will help you if you are trying to implement a countdown:
Public Class CountdownStopwatch
Inherits Stopwatch
Public Property Period As TimeSpan
Public ReadOnly Property Remaining As TimeSpan
Get
Dim timeRemaining = Period - Elapsed
Return If(timeRemaining > TimeSpan.Zero, timeRemaining, TimeSpan.Zero)
End Get
End Property
Public ReadOnly Property IsExpired As Boolean
Get
Return Elapsed >= Period
End Get
End Property
End Class
It's basically a Stopwatch with extra countdown functionality. For instance, if you want to do something for 10 minutes then you can do this:
myCountdownStopwatch.Period = TimeSpan.FromMinutes(10)
myCountDownStopwatch.Restart()
In the Tick event of your Timer, you can display the time remaining and prompt the user when time expires like this:
timeReaminingLabel.Text = myCountdownStopwatch.Remaining.ToString("m\:ss")
If myCountdownStopwatch.IsExpired Then
myTimer.Stop()
myCountdownStopwatch.Stop()
myCountdownStopwatch.Reset()
'Prompt user here.
End If

Related

Countdown timer with time format(00:00:00) in vba access

I am creating Access db which needs auto close the db using timer count down. for example, if I give 5 min then it should start count down displaying this time format 00:04:59
I have found several pieces of tips checking the web, but did not manage to fit the pieces to one working piece.
Below is working perfect. but in output i can see only min and sec 0:00. How to add code for hours as well (format 00:00:00)? I tried to add hours but it is not working
Public Loops As Integer
Private Sub Form_Load()
Me.TimerInterval = 1000
Form_Timer
End Sub
Private Sub Form_Timer()
Static StartTime As Date
Dim SecondsToCount As Integer
SecondsToCount = 15 'Set this variable to the total number of seconds to
count down
If Loops = 0 Then StartTime = Time
Min = (SecondsToCount - DateDiff("s", StartTime, Time)) \ 60
Sec = (SecondsToCount - DateDiff("s", StartTime, Time)) Mod 60
Me.TimeLeft.Caption = "Form will close in " & Min & ":" & Format(Sec,"00")
Loops = Loops + 1
If Me.TimeLeft.Caption = "Form will close in 0:00" Then
DoCmd.Close acForm, Me.Name
End If
End Sub
Use a textbox for display, Timer to get a better resolution, and a TimerInterval of 100 for a closer match.
Complete code-behind module of the form:
Option Compare Database
Option Explicit
Private WatchTime As Date
Private Sub Form_Load()
' Specify count down time.
Const CountDownSeconds As Long = 15
WatchTime = DateAdd("s", CountDownSeconds, Now)
Me!txtCount.Value = WatchTime
Me.TimerInterval = 100
End Sub
Private Sub Form_Timer()
Const SecondsPerDay As Long = 86400
Dim TimeLeft As Date
TimeLeft = CDate(WatchTime - Date - Timer / SecondsPerDay)
Me!txtCount.Value = TimeLeft
If TimeLeft <= 0 Then
Me.TimerInterval = 0
MsgBox "Time ran out!", vbExclamation, "Exit"
DoCmd.Close acForm, Me.Name
End If
End Sub

how to stop user adding number to NumericUpDown after it reach a vlaue

I have 10 NumericUpDowns. I want them when to reach the limit of 14 and then the last NumericUpDown the user clicked only can be decreased or stay the same after the msgbox display, I set the limit to each is 4
Private Sub Chkval()
Dim storeval(11) As Integer
storeval(0) = NumericUpDown1.Value
storeval(1) = NumericUpDown2.Value
storeval(2) = NumericUpDown3.Value
storeval(3) = NumericUpDown4.Value
storeval(4) = NumericUpDown5.Value
storeval(5) = NumericUpDown6.Value
storeval(6) = NumericUpDown13.Value
storeval(7) = NumericUpDown14.Value
storeval(8) = NumericUpDown18.Value
storeval(9) = NumericUpDown19.Value
If storeval.Sum > 14 Then
MsgBox("ok")
End If
End Sub
Just hook all the 10 numericupdowns' ValueChanged event to a single event handler and in that handler check if the sum of all the values has exceeded 14. If so, then decrease the sender numericupdown's value so that the sum = 14.

Need A Timer To Fire At Specific Time And Every 5 Minutes Until Job Complete

I need help setting up a specific type of timer for my application. My scenario is this:
I want to run a timer at a specific time of day (say 4:00AM). That timer then executes a number of different events that each go off and grab data from a database and process it (using background workers). All the different events take different times to finish (could be 30 seconds, could be 5 minutes). I want to continuously enter the timer event every 5 minutes thereafter checking if all events have finished. If so, stop the timer and restart it again at 4:00AM the next morning and so on.
So the process would look like this:
04:00AM - Start Timer and initiate background workers
04:05AM - Check again to see if processes have completed (if so, stop timer)04:10AM - Check again to see if processes have completed (if so, stop timer)
And so on....
I already have my background worker code that processes my database information. So I just need help setting up the timer.
So far I have the following in my Tick event:
Private Sub tmr_Maintenance_Tick(sender As Object, e As EventArgs) Handles tmr_Maintenance.Tick
Dim CurrentTime As Date
Dim CurrHour As Integer
CurrentTime = DateTime.Now
CurrHour = CurrentTime.Hour
'Automatic Sales Import
With My.Settings
If CurrHour = 4 Then
If Not .Maintenance_Ran Then
CreateLog("Maintenance Started")
If Not .Yesterdays_Sales_Imported Then
CreateLog("Importing Yesterday's Sales From Portal")
If Not YesterdaysSales_Worker.IsBusy Then YesterdaysSales_Worker.RunWorkerAsync()
End If
If Not .WTD_Sales_Imported Then
CreateLog("Importing Week To Date Sales From Portal")
If Not WeekToDateSales_Worker.IsBusy Then WeekToDateSales_Worker.RunWorkerAsync()
End If
If Not .LW_Sales_Imported Then
CreateLog("Importing Last Week Sales From Portal")
If Not LastWeekSales_Worker.IsBusy Then LastWeekSales_Worker.RunWorkerAsync()
End If
If .Yesterdays_Sales_Imported = True And .WTD_Sales_Imported = True And .LW_Sales_Imported = True Then
.Maintenance_Ran = True
End If
End If
Else
.Maintenance_Ran = False
End If
End With
My.Settings.Save()
End Sub
Any help appreciated thanks.
Here's a basic framework you can start from:
Public Class Form1
Private Enum MaintenanceState
WaitingToStart
Started
End Enum
Private Target As DateTime
Private state As MaintenanceState = MaintenanceState.WaitingToStart
Private MaintenanceTime As New TimeSpan(4, 0, 0) ' 4:00 am
Private WaitingInterval As New TimeSpan(0, 5, 0) ' Five minutes
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Target = GetNextMaintenanceTarget(MaintenanceTime)
tmr_Maintenance.Interval = 1000
tmr_Maintenance.Start()
End Sub
Private Sub tmr_Maintenance_Tick(sender As Object, e As EventArgs) Handles tmr_Maintenance.Tick
' optionally display time remaining until next target
Dim ts As TimeSpan = Target.Subtract(DateTime.Now)
Label1.Text = ts.ToString("hh\:mm\:ss")
' see if we've hit the target
If DateTime.Now >= Target Then
tmr_Maintenance.Stop()
Select Case state
Case MaintenanceState.WaitingToStart
' ... start all the jobs ...
state = MaintenanceState.Started
Target = DateTime.Now.Add(WaitingInterval)
Case MaintenanceState.Started
' ... check to see if the jobs are all done ...
If Not AllJobsCompleted Then
Target = DateTime.Now.Add(WaitingInterval)
Else
state = MaintenanceState.WaitingToStart
Target = GetNextMaintenanceTarget(MaintenanceTime)
End If
End Select
tmr_Maintenance.Start()
End If
End Sub
Private Function GetNextMaintenanceTarget(ByVal time As TimeSpan) As DateTime
Dim dt As DateTime = DateTime.Today.Add(time)
If DateTime.Now > dt Then
dt = dt.AddDays(1) ' already past target time for today, next start is tomorrow
End If
Return dt
End Function
End Class
Instead of firing your timer every second and checking the current hour (which seems problematic anyway) why not calculate how many milliseconds until 4 am and set the timer to fire at that time?
Dim timer = New Timer()
timer.Interval = MillisecondsUntilNextFourAm
...
Function MillisecondsUntilNextFourAm() As Integer
Dim now = DateTime.Now()
If now.Hour < 4 Then
Return (TimeSpan.FromHours(4) - now.TimeOfDay).TotalMilliseconds
Else
Return (TimeSpan.FromHours(28) - now.TimeOfDay).TotalMilliseconds
End If
End Function
You could do something similar if you then want the timer to fire again in 5 minutes. I would set the timer's AutoReset property to False and call Start each time after setting the interval.

Null Reference Exception was Unhandled

This is a very simple code. I am just beginning to use vb. Im making a game where you reorder the shuffled numbers into the correct order. You try to solve the puzzle in the least amount of time and least amount of clicks, and the next time you play, you try to get a lower score (or beat that record). You have sixteen buttons (4x4) and fifteen numbers. There is a checkbutton function to see if the puzzle is solved Every time I debug the program, it highlights the Clicks and FinalTime and says Null Reference Exception was Unhandled. Heres some of the code.
Public Class Form1
Dim Clicks As Integer = 0 'The variable that counts the number of times you clicked
Dim Time As Integer 'The vairable that holds the time
Dim TimeMin As Integer 'The variable that holds the minutes
Dim TimeSec As Integer 'The variable that holds the seconds
Dim FinalTime As String 'The variable that holds the final time (minutes and seconds)
Dim lngArray() As String = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", ""} {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", ""}
Dim NumArray() As Integer
Dim NumArray1() As String
Private Sub CheckButton(ByRef Butt1 As Button, ByRef Butt2 As Button)
If Butt2.Text = "" Then 'Checks if the button around the clicked number is empty "" It's the location of the empty square that you want the number in Butt1 to move to.
Butt2.Text = Butt1.Text 'If it is, the value from Butt2 will "copy and paste" into Butt1
Butt1.Text = "" 'Butt1 will keep the value and the value in Butt2 will clear ""
Clicks += 1 'Incrementing Each click by only 1. It's a counter. In addition, the code above only allows the click to increment by 1 if the number has moved. If you just click on a number that can't move, the click would not count.
End If
If Clicks > 1 Then
lblTotal.Text = Clicks & " Clicks" 'Shows the total amount of clicks when it is greater than one
Else
lblTotal.Text = Clicks & " Click" 'Shows the total amount of clicks when it is one
End If
End Sub
Private Sub CheckSolved() 'A private sub that checks if the puzzle is solved ,restarts the count, and stops the time
Dim strName As String = "" 'The variable that has the string of the winners name
If Me.Button1.Text = "1" And Me.Button2.Text = "2" And Me.Button3.Text = "3" And Me.Button4.Text = "4" And Me.Button5.Text = "5" And Me.Button6.Text = "6" And Me.Button7.Text = "7" And Me.Button8.Text = "8" And Me.Button9.Text = "9" And Me.Button10.Text = "10" And Me.Button11.Text = "11" And Me.Button12.Text = "12" And Me.Button13.Text = "13" And Me.Button14.Text = "14" And Me.Button15.Text = "15" Then 'Checks if the numbers are in the correct buttons
Timer1.Enabled = False 'Stops the time
strName = InputBox("What is your name", "Name of winner") 'Get's the winners name
MessageBox.Show("In " & FinalTime & " , you solved the puzzle in " & Me.Clicks & " clicks! Congratulations " & strName) 'Messagebox showing how many times you clicked to solve the puzzle. It gets the name you typed into the inputbox (strname) and displays it
Call Restart() 'Shuffles the buttons and restarts the game when you win
Call Record(NumArray, NumArray1)
End If
End Sub
Private Sub Record(ByVal NumArray() As Integer, ByVal NumArray1() As String)
'Make timemin array and then make time array. Then make click array
For i As Integer = 0 To 1000
NumArray(i) = Clicks 'This is where the Null Reference error occured
i = +1
Array.Sort(NumArray) 'sorting the array values from least to greatest
Next i
lblRecordClicks.Text = NumArray(0) & " Clicks" 'displaying the lowest number of clicks in the label
For k As Integer = 0 To 1000 'Making an integer that captures 1000 values
NumArray1(k) = FinalTime 'This is where the Null Reference error occured
k = +1
Array.Sort(NumArray1) 'sorting the array values from least to greatest
Next k
lblRecordTime.Text = NumArray1(0) 'displaying the lowest time in the label
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Call Times()
End Sub
Private Sub Shuffle(ByVal lngArray As Object) 'Shuffles the values of the Array
Dim i As Long
Dim iMin As Long
Dim iMax As Long
Dim lngReplace As Long
Dim varSwap As Object
iMin = LBound(lngArray)
iMax = UBound(lngArray)
For i = iMax To iMin + 1 Step -1
lngReplace = Int((i - iMin + 1) * Rnd() + iMin)
varSwap = lngArray(i)
lngArray(i) = lngArray(lngReplace)
lngArray(lngReplace) = varSwap
Next
Button1.Text = lngArray(0)
Button2.Text = lngArray(1)
Button3.Text = lngArray(2)
Button4.Text = lngArray(3)
Button5.Text = lngArray(4)
Button6.Text = lngArray(5)
Button7.Text = lngArray(6)
Button8.Text = lngArray(7)
Button9.Text = lngArray(8)
Button10.Text = lngArray(9)
Button11.Text = lngArray(10)
Button12.Text = lngArray(11)
Button13.Text = lngArray(12)
Button14.Text = lngArray(13)
Button15.Text = lngArray(14)
Button16.Text = lngArray(15)
End Sub
Private Sub RestartToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RestartToolStripMenuItem.Click
Call Restart()
Call Me.btnStart_Click(sender, e) 'Call the button click to enable all buttons
End Sub
Private Sub Times()
Time = Time + 1 'Increase the time by 1 second every interval
TimeSec = TimeSec + 1 'Increase the time by 1 second every interval
TimeMin = Convert.ToInt32(TimeSec \ 60) 'Takes the whole number of the amount of seconds divided by 60 and leaves out the remainder
If Time >= 60 Then
Time = 0
End If
'If the seconds pass 59 (and they do), it restarts to 0
FinalTime = TimeMin & " min " & Time & " seconds" 'Final time is the string displayed showing the final time
lblTime.Text = FinalTime 'The label displays the final time
End Sub
Private Sub Restart()
Time = 0 'Resets the time
Clicks = 0 'Resets the amount of clicks
lblTotal.Text = "" 'Clears the label
lblCheat.Visible = False
lblTotal.Visible = True
lblClicks.Visible = True
lblQuote.Visible = True
lblRecordClicks.Visible = True
lblRecordTime.Visible = True
'If the user cheated and hit the solve button and wants to restart and solve the puzzle on their own, then he can. Turning these label settings to true allows you to see them again
Call Shuffle(lngArray) 'Shuffles the numbers
Timer1.Enabled = True 'Continues the time when it resets to 0
End Sub
Public Sub RefreshEverythingToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RefreshEverythingToolStripMenuItem.Click
Timer1.Enabled = False 'Pauses the timer
If MessageBox.Show("Do you want to restart everything?", "Restart Game", MessageBoxButtons.YesNo, MessageBoxIcon.Information) = DialogResult.Yes Then
Time = 0
TimeSec = 0
'Resets the time
Clicks = 0 'Resets the amount of clicks
lblTotal.Text = "" 'Clears the label
lblRecordClicks.Text = "" 'Resets the record click
lblRecordTime.Text = "" 'Resets the record time
End If
Call Shuffle(lngArray) 'Shuffles the numbers
Timer1.Enabled = True 'Continues the timer if no is selected
ReDim NumArray(1000) 'Clears the array data that was captured
ReDim NumArray1(1000) 'Clears the array data that was captured
End Sub
End Class
If you do decide to help (and I HOPE you do) could you try to avoid using "computer" talk and try to "dumb it down for me". Like I said before, I am new at this. Thanks for your time.
You are trying to save the values to an array. When you define an array like Dim NumArray() As Integer there are no bounds set for the array (the array is basically Nothing) and if you then try to access an array item you encounter the Null reference exception.
You only set the array bounds in Public Sub RefreshEverythingToolStripMenuItem_Click. Now I don't know all of your code but if the game is started without the user specifically clicking this button then your array will be Nothing.
You have to make sure that the array bounds are always set before a game is started.
You could also look into more abstract array-like types in .NET. For example you could try a list. A List is practically an array with arbitrary bounds. You define the List with a specific type using the Of keyword and you can then add items to it with the lists Add method, remove items, sort the list etc.
Define as a global variable:
Dim FinalTimes as New List(Of Integer)
Dim FinalClicks as New List(Of Integer)
Make sure you use the New keyword here. This means that a new object of class List will be created. Otherwise you would encounter Null Reference Exceptions on the lines below again.
When the user solves the puzzle you then do:
FinalTimes.Add(FinalTime)
FinalClicks.Add(Clicks)
FinalTimes.Sort
FinalClicks.Sort
This will basically increase the length of the list by one, write the FinalTime/Clicks value into the last item and then resort both lists. Ideas: For a highscore you might want to connect FinalTime, Clicks and Player Name into a structure and use the IComparer Interface to let the user sort the high score list by name/Time/Clicks.
Jens
PS: Before I forget: The For loops in which the exception occured in your code make no real sense. First problem is that in their current forms they would be infinite loops because you always set i to 1 in the loop while the loop ends when i=1000 (which would never happen, obviously). I think you meant i=i+1 or shorter i += 1 there. But they still make little sense. I tried it out to see what happens exactly (which is not obvious :-)) and half of your high score is overwritten by the new value etc. I think the above method will be easier. :-)

Trouble with Timer_tick not stopping

I'm very new to programming and vb.net, trying to self teach more so as a hobby, as I have an idea for a program that I would find useful, but I am having trouble getting past this issue and I believe it is to do with the timer.
I have a form of size.(600,600) with one button of size.(450,150) that is set location(100,50) on the form. When clicked I want to move down it's own height, then add a new button in it's place. The code included below works as desired for the first two clicks, but on the third click the button keeps moving and the autoscroll bar extends. I initially thought it was the autoscroll function or the location property, but realised that as the button keeps moving, the timer hasn't stopped. I am aware that the code is probably very clunky in terms of achieving the outcome, and that there are a few lines/variables that are currently skipped over by the compiler (these are from older attempts to figure this out).
I have looked around and can't find the cause of my problem. Any help would be greatly appreciated. Apologies if the code block looks messy - first go.
Public Class frmOpenScreen
Dim intWButtons, intCreateButtonY, intCreateButtonX 'intTimerTick As Integer
Dim arrWNames() As String
Dim ctrlWButtons As Control
Dim blnAddingW As Boolean
Private Sub btnCreateW_Click(sender As System.Object, e As System.EventArgs) Handles btnCreateW.Click
'Creates new Button details including handler
Dim strWName, strWShort As String
Dim intCreateButtonY2 As Integer
Static intNumW As Integer
Dim B As New Button
strWName = InputBox("Please enter the name name of the button you are creating. Please ensure the spelling is correct.", "Create W")
If strWName = "" Then
MsgBox("Nothing Entered.")
Exit Sub
End If
strWShort = strWName.Replace(" ", "")
B.Text = strWName
B.Width = 400
B.Height = 150
B.Font = New System.Drawing.Font("Arial Narrow", 21.75)
B.AutoSizeMode = Windows.Forms.AutoSizeMode.GrowAndShrink
B.Anchor = AnchorStyles.Top
B.Margin = New Windows.Forms.Padding(0, 0, 0, 0)
'Updates Crucial Data (w name array, number of w buttons inc Create New)
If intNumW = 0 Then
ReDim arrWNames(0)
Else
intNumW = UBound(arrWNames) + 1
ReDim Preserve arrWNames(intNumW)
End If
arrWNames(intNumW) = strWShort
intNumW = intNumW + 1
intWButtons = WButtonCount(intWButtons) + 1
'updates form with new button and rearranges existing buttons
intCreateButtonY = btnCreateW.Location.Y
intCreateButtonX = btnCreateW.Location.X
‘intTimerTick = 0
tmrButtonMove.Enabled = True
‘Do While intTimerTick < 16
‘ 'blank to do nothing
‘Loop
'btnCreateW.Location = New Point(intCreateButtonX, intCreateButtonY + 150)
B.Location = New Point(intCreateButtonX, intCreateButtonY)
Me.Controls.Add(B)
B.Name = "btn" & strWShort
intCreateButtonY2 = btnCreateW.Location.Y
If intCreateButtonY2 > Me.Location.Y Then
Me.AutoScroll = False
Me.AutoScroll = True
Else
Me.AutoScroll = False
End If
'MsgBox(intCreateButtonY)
End Sub
Function WButtonCount(ByRef buttoncount As Integer) As Integer
buttoncount = intWButtons
If buttoncount = 0 Then
Return 1
End If
Return buttoncount
End Function
Public Sub tmrButtonMove_Tick(sender As System.Object, e As System.EventArgs) Handles tmrButtonMove.Tick
Dim intTimerTick As Integer
If intTimerTick > 14 Then
intTimerTick = 0
End If
If btnCreateW.Location.Y <= intCreateButtonY + 150 Then
btnCreateW.Top = btnCreateW.Top + 10
End If
intTimerTick += 1
If intTimerTick = 15 Then
tmrButtonMove.Enabled = False
End If
End Sub
End Class
So my current understanding is that the tick event handler should be increasing the timertick variable every time it fires, and that once it has hits 15 it should diable the timer and stop the button moving, but it is not doing so.
Thanks in advance.
IntTimerTick is initialized to 0 at the beginning of every Tick event. This won't happen if you declare it to be static:
Static Dim intTimerTick As Integer