LoginSignup
0
0

More than 3 years have passed since last update.

[不具合あり] C++ Builder XE4 > TTimer > 指定時刻(hh, mm)に処理をする > TTimer->Intervalの設定 > テストしにくい

Last updated at Posted at 2017-10-18

注意: 2018/01/05 下記のコードには不具合があります。ミリ秒の差が検討されていないため、タイマー処理が失敗します。修正版(v0.2)は下記に記載しました。

C++ Builder 10.2 Tokyo > 実装ミス > タイマー処理関連 > 指定時刻(hh, mm)に処理をする > 処理時刻のずれがある > 修正版v0.2

動作環境
C++ Builder XE4

処理概要

  • Timeのhhとmmを指定する
  • (時==hh)と(分==mm)となる日時に処理をする
  • 現在時刻と指定時刻が一致する場合は、次の日とする

TTimer->Intervalを使った実装とした。

code v0.1

Unit1.h
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE で管理されるコンポーネント
    TEdit *E_hh;
    TEdit *E_mm;
    TButton *B_start;
    TMemo *Memo1;
    TLabel *Label1;
    TTimer *TimerAlarm;
    void __fastcall B_startClick(TObject *Sender);
    void __fastcall TimerAlarmTimer(TObject *Sender);
private:    // ユーザー宣言
    TDateTime __fastcall getNextAlarmDateTime(TDateTime now, int hh, int mm);
    void __fastcall startAlarmTimer(void);
public:     // ユーザー宣言
    __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include <DateUtils.hpp>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------

/*
v0.1 Oct. 18, 2017
    - add startAlarmTimer()
    - add [TimerAlarm]
    - add getNextAlarmDateTime()
*/

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    TimerAlarm->Enabled = false;
}
//---------------------------------------------------------------------------

TDateTime __fastcall TForm1::getNextAlarmDateTime(TDateTime now, int hh, int mm)
{
    TDateTime res = RecodeHour(Now(), hh);
    res = RecodeMinute(res, mm);
    res = RecodeSecond(res, 0);
    if (res <= Now()) {
        res = IncDay(res, 1);
    }
    return res;
}

void __fastcall TForm1::B_startClick(TObject *Sender)
{
    startAlarmTimer();
}

void __fastcall TForm1::startAlarmTimer(void)
{
    // 1. フォームからの読取り
    int next_hh, next_mm;
    try {
        next_hh = StrToIntDef(E_hh->Text, -1);
        next_mm = StrToIntDef(E_mm->Text, -1);
    } catch (Exception &exc) {
        ShowMessage(exc.Message);
        return;
    }
    if (next_hh < 0 || next_mm < 0) {
        Memo1->Lines->Add(L"Error: set numerical values for [hh] and [mm]");
        return; // error
    }

    // 2. 次の日時取得
    TDateTime nextdt = getNextAlarmDateTime(Now(), next_hh, next_mm);

    String msg = "now: " + Now().DateTimeString() + L" next: " + nextdt.DateTimeString();
    Memo1->Lines->Add(msg);

    // 3. タイマーセット
    __int64 intvl = SecondsBetween(Now(), nextdt);
    TimerAlarm->Enabled = false;
    TimerAlarm->Interval = intvl * 1000; // msec
    TimerAlarm->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::TimerAlarmTimer(TObject *Sender)
{
    TimerAlarm->Enabled = false;

    String msg = L"Expired @ " + Now().DateTimeString();
    Memo1->Lines->Add(msg);

    startAlarmTimer();
}
//---------------------------------------------------------------------------

結果

qiita.png

OnTimerにてstartAlarmTimer()をコールすることで繰返し処理をすることはできる。

現状の問題はテストをしにくい点。1日1回のイベントを数日かけてテストするのは効率が悪い。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0