HeyCHのブログ

慢性疲労のへいちゃんです

【C#】簡単なストップウォッチを作ろう その2

続行可能な一時停止、停止できるストップウォッチ

続行可能な一時停止っていうのは、「Pause」ボタンで一時停止した後、再度「Start」を押すと停止した時間から続行できる感じのやつで、停止っていうのは、Stopボタンを押すともれなく「00:00:00.000」に戻るというもの。
という事で、UI的には、表示用のラベルとStartボタンとStopボタンを配置します。

f:id:HeyCH:20200328001012p:plain
ストップウォッチ

停止(Stop)

Stopする場合は前回作ったストップウォッチのストップの処理が終わった後、LabelのTextを「00:00:00.000」に設定してやればいいだけなのですが、ちょっと面倒です。
以下のように、BackgroundWorkerの処理が終わったイベント(Bw_RunWorkerCompleted)を拾ってラベルを書き換えてやる必要があります。

        DateTime now;
        DateTime startTime;
        BackgroundWorker bw;
        bool isStoped = false;
        private void Form1_Load(object sender, EventArgs e)
        {
            bw = new BackgroundWorker();
            bw.DoWork += Bw_DoWork;
            bw.RunWorkerCompleted += Bw_RunWorkerCompleted;
            bw.WorkerSupportsCancellation = true;
        }
        private void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            button1.Text = "Start";
            if (isStoped)
            {
                label1.Text = "00:00:00.000";
                isStoped = false;
            }
        }
        private void button2_Click(object sender, EventArgs e)
        {
            isStoped = true;
            bw.CancelAsync();
        }

続行可能な一時停止(Pause)

一時停止はLabelに表示していたTimeSpanをクラス変数にして記憶しておき、startTimeを取得するとき、DateTime.Nowから引いてやることで続行可能な一時停止を実現することができました。
何かわからないことがあればコメントで聞いてください。(べ、べつに説明が面倒とかそういうんじゃないんだからね)

        DateTime now;
        DateTime startTime;
        BackgroundWorker bw;
        TimeSpan ts;
        bool isStoped = false;
        private void Form1_Load(object sender, EventArgs e)
        {
            ts = new TimeSpan(0);
            bw = new BackgroundWorker();
            bw.DoWork += Bw_DoWork;
            bw.RunWorkerCompleted += Bw_RunWorkerCompleted;
            bw.WorkerSupportsCancellation = true;
        }

        private void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            button1.Text = "Start";
            if (isStoped)
            {
                ts = new TimeSpan(0);
                label1.Text = "00:00:00.000";
                isStoped = false;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (button1.Text == "Start")
            {
                startTime = DateTime.Now- ts;
                bw.RunWorkerAsync();
                button1.Text = "Pause";
            }
            else
            {
                bw.CancelAsync();
                button1.Text = "Start";
            }
        }
        private void button2_Click(object sender, EventArgs e)
        {
            isStoped = true;
            if (bw.IsBusy)
            {
                bw.CancelAsync();
            }
            else
            {
                ts = new TimeSpan(0);
                label1.Text = "00:00:00.000";
                isStoped = false;
            }
        }
        private void Bw_DoWork(object sender, DoWorkEventArgs e)
        {
            while (!bw.CancellationPending)
            {
                now = DateTime.Now;
                ts = now - startTime;
                try
                {
                    Invoke((MethodInvoker)delegate ()
                    {
                        label1.Text = String.Format("{0:D2}:{1:D2}:{2:D2}.{3:D3}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds);
                    });
                }
                catch (Exception ex)
                {
                }
            }
        }