Home > Blockchain >  Color change at certain time vb.net
Color change at certain time vb.net

Time:12-11

This should be fairly straight forward but I cannot figure it out,

I have a button on a form with the default back colour of silver, when the button is pushed it turns red,

If the backcolor is red and it reaches a certain time of the day I want the backcolor to change to black. The code I have used is as follows

If CAButton.BackColor = Color.Red And DateTime.Now > #11:48:00# Then
        CAButton.BackColor = Color.Black

However for some reason now, it doesnt matter what time it is, as soon as I push the button it automatically changes to black, theres obviously something missing from the code but I cant tell what, can anyone see whats wrong?

CodePudding user response:

Now is the complete date with time. You need to compare it to a complete date with time.

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    If Button1.BackColor = Color.Red And DateTime.Now > New DateTime(Now.Year, Now.Month, Now.Day, 11, 48, 0) Then
        Button1.BackColor = Color.Black
    End If
End Sub

CodePudding user response:

In addition to Mary's answer, you can check just the TimeOfDay from DateTime.Now against a TimeSpan:

Private targetTime As New TimeSpan(11, 48, 0)

Private Sub CAButton_Click(sender As Object, e As EventArgs) Handles CAButton.Click
    If CAButton.BackColor = Color.Red And DateTime.Now.TimeOfDay >= targetTime Then
        CAButton.BackColor = Color.Black
    End If
End Sub

CodePudding user response:

You can achieve that with a Timer which is set to fire at the desired time, which you can set at the time the button is clicked.

I put a button named CAButton on a new form in a new Windows Forms project with this code:

Public Class Form1

    Private caBlackTime As New TimeSpan(19, 0, 0)
    Private tim As Timer = Nothing

    Private Sub Tim_Tick(sender As Object, e As EventArgs)
        tim.Stop()
        If CAButton.BackColor = Color.Red Then
            CAButton.BackColor = Color.Black
        End If

    End Sub

    Private Sub CAButton_Click(sender As Object, e As EventArgs) Handles CAButton.Click
        If tim IsNot Nothing Then tim.Dispose()

        Dim timeUntilChangeColour = caBlackTime - DateTime.Now.TimeOfDay

        If timeUntilChangeColour > TimeSpan.Zero Then
            CAButton.BackColor = Color.Red
            tim = New Timer With {.Interval = CInt(timeUntilChangeColour.TotalMilliseconds)}
            AddHandler tim.Tick, AddressOf Tim_Tick
            tim.Start()

        Else
            CAButton.BackColor = Color.Black

        End If

    End Sub

    Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
        ' Tidy up
        If tim IsNot Nothing Then tim.Dispose()

    End Sub

End Class

There are several sorts of Timer available, but this one is the Windows.Forms.Timer, which is the most suitable in this particular case.

CodePudding user response:

Ah, @AndrewMorton beat me to it! Well I'm not going to let all this code go to waste...

Here is a solution which sets the color then sets it back automatically, without any button click, at specified intervals daily. Yes, daily - if the application is left open then it will happen tomorrow, and the next day, etc. The colors and time of day of each color are configurable. It also handles the case when the time has already passed when the user starts the application, and the case when the user starts the application between red and black. I use System.Threading.Timer here. Note: the accuracy of using any timer in .NET may drift over time.

' declare the timers, will be initialized in Form_Load
Private turnColor1Timer As System.Threading.Timer
Private turnColor2Timer As System.Threading.Timer
' set the two colors at this level for a single point of configuration
Private ReadOnly color1 As Color = Color.Red
Private ReadOnly color2 As Color = Color.Black
' first color time is set here for ease of configuration
Private ReadOnly color1TimeOfDay As New TimeSpan(11, 48, 0)
' second color time is set here based on previous color   some timespan, for ease of configuration
Private ReadOnly color2TimeOfDay As New TimeSpan(color1TimeOfDay.Add(New TimeSpan(0, 1, 0)).Ticks)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    ' not sure if you want initial state to be black?
    turnColorTimerTick(color2)
    ' initialize the times to change colors to today
    Dim turnColor1Time = DateTime.Now.Date.Add(color1TimeOfDay)
    Dim turnColor2Time = DateTime.Now.Date.Add(color2TimeOfDay)
    ' check if that time has already passed today, if so set to tomorrow and change color
    If turnColor1Time.CompareTo(DateTime.Now) < 0 Then
        turnColorTimerTick(color1)
        turnColor1Time = turnColor1Time.AddDays(1)
    End If
    If turnColor2Time.CompareTo(DateTime.Now) < 0 Then
        turnColorTimerTick(color2)
        turnColor2Time = turnColor2Time.AddDays(1)
    End If
    ' initialize both timers to their appropriate times
    turnColor1Timer = New System.Threading.Timer(AddressOf turnColorTimerTick, color1, CInt(turnColor1Time.Subtract(DateTime.Now).TotalMilliseconds), CInt(TimeSpan.FromDays(1).TotalMilliseconds))
    turnColor2Timer = New System.Threading.Timer(AddressOf turnColorTimerTick, color2, CInt(turnColor2Time.Subtract(DateTime.Now).TotalMilliseconds), CInt(TimeSpan.FromDays(1).TotalMilliseconds))
End Sub

Private Sub turnColorTimerTick(state As Object)
    ' since it ticks in a background thread, must check if you need to invoke back to UI and call Invoke as needed
    If CAButton.InvokeRequired Then
        CAButton.Invoke(New Action(Of Object)(AddressOf turnColorTimerTick), {state})
    Else
        ' get color from argument passed
        Dim color = DirectCast(state, Color)
        CAButton.BackColor = color
    End If
End Sub
' this is put here because the timers should be disposed of
' if you choose to do this, you must remove Dispose from Form.Designer code
' (compiler error will alert you of this if you don't)
' of course, you could just modify the Dispose in Form.Designer,
' but I like to keep any code I have modified in the Form code instead
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
    Try
        If disposing Then
            components?.Dispose()
        End If
        turnColor1Timer?.Dispose()
        turnColor2Timer?.Dispose()
    Finally
        MyBase.Dispose(disposing)
    End Try
End Sub
  • Related