Изменение цвета в определенное время vb.net

#vb.net

#vb.net

Вопрос:

Это должно быть довольно просто, но я не могу понять это,

У меня есть кнопка в форме с задним цветом по умолчанию серебристого цвета, при нажатии кнопки она становится красной,

Если задний цвет красный, и он достигает определенного времени суток, я хочу, чтобы задний цвет изменился на черный. Код, который я использовал, выглядит следующим образом

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

Однако по какой-то причине сейчас не имеет значения, в какое время, как только я нажимаю кнопку, она автоматически становится черной, в коде явно чего-то не хватает, но я не могу сказать, что, кто-нибудь может увидеть, что не так?

Комментарии:

1. Если кнопка нажата через определенное время, должна ли она сразу же стать черной? Вы хотите, чтобы цвет фона кнопки снова изменился на красный, если он появится на следующий день?

2. Привет @AndrewMorton, идея этого заключается в том, что если он достигнет 7 вечера, а кнопка все еще красная, я бы хотел, чтобы она стала черной без какого-либо ввода от пользователя

3. Если вы хотите, чтобы он автоматически менялся на черный, не требуя щелчка пользователя, то вам нужно будет настроить механизм для определения либо текущего времени, либо для срабатывания в указанное время. Это можно сделать с помощью таймера, который периодически опрашивает текущее время, или путем вычисления продолжительности времени до целевого времени и настройки либо таймера с этим интервалом, либо путем перевода задачи / потока в спящий режим на эту продолжительность.

Ответ №1:

В дополнение к ответу Мэри, вы можете проверить только TimeOfDay от DateTime.Now против 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
 

Ответ №2:

Вы можете добиться этого с помощью таймера, который настроен на срабатывание в нужное время, которое вы можете установить в момент нажатия кнопки.

Я поместил кнопку с именем CAButton в новую форму в новом проекте Windows Forms с помощью этого кода:

 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
 

Существует несколько видов доступных таймеров, но этот — Windows.Формы.Таймер, который является наиболее подходящим в данном конкретном случае.

Ответ №3:

Ах, @AndrewMorton опередил меня в этом! Что ж, я не позволю всему этому коду пропасть даром…

Вот решение, которое устанавливает цвет, а затем возвращает его автоматически, без какого-либо нажатия кнопки, через определенные промежутки времени ежедневно. Да, ежедневно — если приложение оставить открытым, то это произойдет завтра, и на следующий день, и т.д. Цвета и время суток каждого цвета настраиваются. Он также обрабатывает случай, когда время, когда пользователь запускает приложение, уже прошло, и случай, когда пользователь запускает приложение между красным и черным. Я использую System.Threading.Timer здесь. Примечание: точность использования любого таймера в .NET может меняться со временем.

 ' 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
 

Ответ №4:

Now является полной датой со временем. Вам нужно сравнить его с полной датой со временем.

 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
 

Редактировать
Я думаю, что код был бы лучше в таймере.Отметьте событие, чтобы оно произошло автоматически. Установите интервал в одну минуту. Я думаю, что это 60000 миллисекунд. И также приводит к короткому замыканию If. Если первое условие равно false, оно не проверяет второе условие.

 Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    If Button1.BackColor = Color.Red AndAlso DateTime.Now > New DateTime(Now.Year, Now.Month, Now.Day, 11, 48, 0) Then
        Button1.BackColor = Color.Black
    ElseIf Button1.BackColor = Color.Red AndAlso DateTime.Now < New DateTime(Now.Year, Now.Month, Now.Day, 11, 48, 0) Then
        Button1.BackColor = Color.Red
    End If
End Sub
 

Комментарии:

1. Спасибо, Мэри, это работает так, что если я нажму кнопку до 11:48, она станет красной, а после 11:48 — черной, однако, если она достигнет 11:48, а кнопка станет красной, она не изменится на черный, чего я и пытаюсь добиться, есть идеи о том, как я мог бы это сделать?

2. См. Редактирование моего ответа.

3. Спасибо за редактирование, я, честно говоря, думал, что это было бы гораздо более простым решением, у меня уже есть событие timer.tick, установленное для этого пользователя, поэтому я попытаюсь интегрировать их, поскольку я также хотел, чтобы это приостановило таймер. Спасибо.