Home > database >  C# WinForm Upcounter to hh:mm:ss
C# WinForm Upcounter to hh:mm:ss

Time:10-14

I want to Write a Program like OBS Studio and i wanna add an Upcounter to my Program so that means when i click "Start Stream" it should start the Upcounter from 00:00:00 to 00:00:01 then to 00:00:02 and so on so that i have the "Livetime", how long i am already streaming. And with the "End Stream" Button the Timer should Stop and Reset. How can i do that?

i tried different things but dont had an idea.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace StreamManagement
{
    public partial class MainFormProgram : Form
    {
        public static bool chat_on = true;
        TimeSpan testTime = DateTime.Now.TimeOfDay;
        public MainFormProgram()
        {
            InitializeComponent();
        }

        private void chatOnBtn_Click(object sender, EventArgs e)
        {
            OnLbl.Text = "ON";
            OnLbl.ForeColor = Color.ForestGreen;
            chatOnBtn.BackColor = Color.LightGray;
            chatOffBtn.BackColor = Color.Gray;
        }

        private void chatOffBtn_Click(object sender, EventArgs e)
        {
            OnLbl.Text = "OFF";
            OnLbl.ForeColor = Color.DarkRed;
            chatOffBtn.BackColor = Color.LightGray;
            chatOnBtn.BackColor = Color.Gray;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            OnLbl.Text = "ON";
            OnLbl.ForeColor = Color.ForestGreen;
            EmoteonlyOnOff.Text = "OFF";
            EmoteonlyOnOff.ForeColor = Color.DarkRed;
            SubchatOnOff.Text = "OFF";
            SubchatOnOff.ForeColor = Color.DarkRed;
        }

        private void EmoteOnlyOnBtn_Click(object sender, EventArgs e)
        {
            EmoteonlyOnOff.Text = "ON";
            EmoteonlyOnOff.ForeColor = Color.ForestGreen;
            EmoteOnlyOnBtn.BackColor = Color.FromArgb(112, 147, 252);
            EmoteOnlyOffBtn.BackColor = Color.FromArgb(50, 100, 150);
        }

        private void EmoteOnlyOffBtn_Click(object sender, EventArgs e)
        {
            EmoteonlyOnOff.Text = "OFF";
            EmoteonlyOnOff.ForeColor = Color.DarkRed;
            EmoteOnlyOffBtn.BackColor = Color.FromArgb(112, 147, 252);
            EmoteOnlyOnBtn.BackColor = Color.FromArgb(50, 100, 150);
        }

        private void SubChatOnBtn_Click(object sender, EventArgs e)
        {
            SubchatOnOff.Text = "ON";
            SubchatOnOff.ForeColor = Color.ForestGreen;
            SubChatOnBtn.BackColor = Color.FromArgb(255, 94, 255);
            SubChatOffBtn.BackColor = Color.FromArgb(192, 0, 192);
        }

        private void SubChatOffBtn_Click(object sender, EventArgs e)
        {
            SubchatOnOff.Text = "OFF";
            SubchatOnOff.ForeColor = Color.DarkRed;
            SubChatOffBtn.BackColor = Color.FromArgb(255, 94, 255);
            SubChatOnBtn.BackColor = Color.FromArgb(192, 0, 192);
        }

        private void startstreamBtn_Click(object sender, EventArgs e)
        {
            timerXD.Start();
        }

        private void timerXD_Tick(object sender, EventArgs e)
        {

        }

        private void timerLbl_Click(object sender, EventArgs e)
        {

        }
    }
}

CodePudding user response:

Just store the start time in a DateTime and then subtract that from the current time to get a TimeSpan. With that TimeSpan you can call ToString() and specify whatever format you want.

Something like:

DateTime startDT;

private void Form1_Load(object sender, EventArgs e)
{
    timerXD.Interval = 1000;
    timerXD.Enabled = false;
}
private void startstreamBtn_Click(object sender, EventArgs e)
{
    label1.Text = "00:00:00";
    startDT = DateTime.Now;
    timerXD.Start();
}
private void timerXD_Tick(object sender, EventArgs e)
{
    String elapsed = DateTime.Now.Subtract(startDT).ToString(@"hh\:mm\:ss");
    label1.Text = elapsed; // display elapsed somehow
}

CodePudding user response:

You can use Stopwatch class from System.Diagnostics namespace for that purpose.

Create a Stopwatch field in your Form class:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    Stopwatch stopwatch = new Stopwatch(); // <-- this one
}

Create a Label (lblTime for example), to which we would set upcounted time and a Button at your Form, which would start Stopwatch (btnStart for example):

enter image description here

Optionally you may add other Buttons to manipulate with Stopwatch:

enter image description here

Add Click handler (ButtonStart_Click for example) to "START" button to run Stopwatch from there. Mark it with async to prevent Form freezes while Stopwatch running:

private async void ButtonStart_Click(object sender, EventArgs e)
{
    stopwatch.Start();

    while (stopwatch.IsRunning)
    {
        lblTime.Text = stopwatch.Elapsed.ToString("hh\\:mm\\:ss");
        await Task.Delay(1000); // Delay between time updates on Form (1 sec)
    }
}

Now you have "upcount timer".

Remarks:

  1. Use stopwatch.Reset(); to stop timer and reset measured time.
  2. Use stopwatch.Stop(); if you want to stop time measurement, but want to keep meaused time. Similar to "Pause".

Complete Form code:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    // "Upcount Timer"
    private readonly Stopwatch stopwatch = new Stopwatch();

    private async void ButtonStart_Click(object sender, EventArgs e)
    {
        stopwatch.Start();

        // Disable START button and enable STOP and PAUSE buttons
        btnStart.Enabled = !(btnPause.Enabled = btnStop.Enabled = true);

        while (stopwatch.IsRunning)
        {
            // Update time in Label on Form
            lblTime.Text = stopwatch.Elapsed.ToString("hh\\:mm\\:ss");
            // Delay between next update
            await Task.Delay(1000);
        }
    }
    private void ButtonPause_Click(object sender, EventArgs e)
    {
        // Stop timer, but not reset measured time
        stopwatch.Stop();
        // Enable START button and disable STOP and PAUSE buttons
        btnStart.Enabled = !(btnPause.Enabled = btnStop.Enabled = false);
    }
    private void ButtonStop_Click(object sender, EventArgs e)
    {
        // Stop timer and reset measured time
        stopwatch.Reset();
        
        // Reset time in Label on Form
        lblTime.Text = "00:00:00";
        // or use stopwatch.Elapsed property - after Reset() it would be 00:00:00
        //lblTime.Text = stopwatch.Elapsed.ToString("hh\\:mm\\:ss");
        
        // Enable START button and disable STOP and PAUSE buttons
        btnStart.Enabled = !(btnPause.Enabled = btnStop.Enabled = false);
    }
}

CodePudding user response:

You can do this with a seperate Task that cancels when you click the button using a CancellationToken Right below your class name you can put this:

public CancellationTokenSource cancellationTokenSource { get; set; }
    public CancellationToken cancellationToken => this.cancellationTokenSource.Token;

Your timer Task can look something like this:

private async Task Timer()
    {
        CancellationToken cancel = this.cancellationToken;
        int s = 0;


        TimeSpan ts = TimeSpan.FromSeconds(s);
        while(!cancel.IsCancellationRequested)
        {
            lbltimer.Text = ts.ToString(@"hh\:mm\:ss");
            await Task.Delay(1000);
            s  ;
            ts = TimeSpan.FromSeconds(s);
        }
    }

Now for the Buttons

Put this in your StartBtn Function

cancellationTokenSource = new();
        Timer();

and this in your StopBtn Function

cancellationTokenSource.Cancel();
  • Related