ホーム > デベロッパ > BREW プログラミング入門 > BREW のタイマー > - 1 / 2 -

BREW のタイマー - 1 / 2 -

BREW のタイマー

BREW のタイマーは、ISHELL_SetTimer インターフェースで設定した一定時間経過後に登録した関数( コールバック関数 )を呼び出すコールバックです。

アプリの概要

最初に、現在時刻を表示します。
※ ITimeCtl インターフェースを使います。
セレクトキーが押されると、日付、時刻、曜日を表示します。
※ IDISPLAY インターフェースを使います。

アプレット構造体

アプレット構造体には ITimeCtl インターフェースのインスタンス変数を追加します。

■アプレット構造体の宣言

typedef struct
{
    AEEApplet a;  // アプレット構造体の先頭メンバは必ず AEEApplet 型にすること

    //画面描画用
    int width;
    int height;
    int font_height;

    ITimeCtl* timectl; // ITimeCtl インターフェースのインスタンス変数
} TimerApp;

OnAppStart 関数

OnAppStart 関数はアプレットが開始時に呼び出されます。

//  アプレットが開始したときに呼び出される
static boolean OnAppStart(TimerApp* app)
{
    AEEDeviceInfo devinfo;
    IShell* shell = app->_a.m_pIShell;

    // IShellインターフェイス関数を使用して、画面サイズを取得する。
    ISHELL_GetDeviceInfo(shell, &devinfo);
    app->width  = devinfo.cxScreen;
    app->height = devinfo.cyScreen;

    MakeTimeCtl(app);
    OnTimerExpired(app);
    return TRUE;
}

MakeTimeCtl 関数

MakeTimeCtl 関数は、ITimeCtl インスタンスを生成し、現在時刻を表示します。

// ITimeCtl の生成
static void MakeTimeCtl(TimerApp* app)
{
    IShell* shell = app->a.m_pIShell;
    AEERect rect;

    //インスタンスの生成
    ISHELL_CreateInstance(shell, AEECLSID_COUNTDOWNCTL, (void**)&app->timectl);
    rect.x = 0;
    rect.y = 10;
    rect.dx = app->width;
    rect.dy = TIMECTL_HEIGHT;
    //描画域の設定
    ITIMECTL_SetRect(app->timectl, &rect);
    //表示時刻の設定
    ITIMECTL_SetTime(app->timectl, GETTIMEMS());
    //Active を FALSE に設定
    ITIMECTL_SetActive(app->timectl, FALSE);
}

OnTimerExpired 関数

BREW のタイマーは、コールバック関数を何ミリ秒後に呼ぶ、という使い方です。タイマーは一度呼ばれるとクリアされます。タイマーを繰り返して使用する場合は、タイマーのコールバック関数の中で ISHELL_SetTimer インターフェースを使って自分自身をコールバック関数としてタイマーの登録します。

//タイマーのコールバック関数
static void OnTimerExpired(TimerApp* app)
{
    //タイマーの再設定
    ISHELL_SetTimer(app->a.m_pIShell, TIMER_INTERVAL,
        (PFNNOTIFY)OnTimerExpired, app);
    //画面描画
    Draw(app);
    return;
}

Draw 関数

Draw 関数は、現在時刻を ITimeCtl インターフェースとIDISPLAY インターフェースの 2 種類で表示します。

// 画面描画
static void Draw(TimerApp* app)
{
    IDISPLAY_ClearScreen(app->a.m_pIDisplay);
    if (app->timectl != NULL) {
        // 時刻の再設定
        ITIMECTL_SetTime(app->timectl, GETTIMEMS());
        // 再描画
        ITIMECTL_Redraw(app->timectl);
    }
    else {
        IDisplay* d = app->a.m_pIDisplay;
        AEERect rect;
        JulianType julian;
        char string[32];
        char week[][5] = {"月", "火", "水", "木", "金", "土", "日"};
        AECHAR wstring[32];

        rect.x = 10;
        rect.dx = app->width - 20;
        rect.dy = TIMECTL_HEIGHT;
        // JulianType に現在時刻の情報を取得
        GETJULIANDATE(GETTIMESECONDS(), &julian);

        rect.y = 10;
        // 年月日を文字列表示
        SPRINTF(string, "%4d/%2d/%2d", julian.wYear, julian.wMonth, julian.wDay);
        STRTOWSTR(string, wstring, sizeof(wstring) * sizeof(AECHAR));
        IDISPLAY_DrawText(d, AEE_FONT_NORMAL, wstring, -1, 0, TIMECTL_HEIGHT, 
        &rect, IDF_ALIGN_RIGHT | IDF_ALIGN_TOP);

        rect.y = 10 + TIMECTL_HEIGHT;
        // 時分秒を文字列表示
        SPRINTF(string, "%2d:%02d:%02d",
            julian.wHour, julian.wMinute, julian.wSecond);
        STRTOWSTR(string, wstring, sizeof(wstring) * sizeof(AECHAR));
        IDISPLAY_DrawText(d, AEE_FONT_NORMAL, wstring, -1, 0, TIMECTL_HEIGHT,&rect,
            IDF_ALIGN_RIGHT | IDF_ALIGN_TOP);

        rect.y = 10 + TIMECTL_HEIGHT * 2;
        // 曜日を文字列表示
        SPRINTF(string, "%s曜日", week[julian.wWeekDay]);
        STRTOWSTR(string, wstring, sizeof(wstring) * sizeof(AECHAR));
        IDISPLAY_DrawText(d, AEE_FONT_NORMAL, wstring, -1, 0, TIMECTL_HEIGHT,
            &rect, IDF_ALIGN_RIGHT | IDF_ALIGN_TOP);

        IDISPLAY_Update(d);
    }
    return;
}

ITimeCtl インターフェースによる時刻表示

// 時刻の再設定: 
// TIMER_INTERVAL の間隔で現在時刻を読み取り ITIMECTL のインスタンスに再設定して、
// AEECLSID_COUNTDOWNCTL 形式で表示する
ITIMECTL_SetTime(app->timectl, GETTIMEMS());
//再描画
ITIMECTL_Redraw(app->timectl);

GETTIMEMS マクロ関数は、午前 0 時からの現在時刻をミリ秒で返します。ITIMECTL_SetTime 関数は、ミリ秒単位の現在時刻を、通常の時刻の表現形式にします。

※ 1. ITimeCtl インターフェースの表示形式

ITimeCtl インターフェースの表示形式は、ISHELL_CreateInstance 関数の第 2 引数で指定します。
以下の 3 種類があります。

第 2 引数が AEECLSID_COUNTDOWNCTL のとき
時間を時、分、秒の単位で表示します。カウントダウンタイマーに利用されることが多いので、AEECLSID_COUNTDOWNCTLというような名前ですが、サンプルプログラムのように毎回時刻を取得して表示すれば時計としても使えます。
第 2 引数が AEECLSID_CLOCKCTL のとき
時間を AM / PM、 時、分 の単位で表示します。
第 2 引数が AEECLSID_STOPWATCHCTL のとき
時間を時、分、秒、100 分の 1 秒の単位で表示します。

※ 2. 時間を表示するだけならば、 ITimeCtl のインスタンスは " FALSE " に設定します。" Active " に設定すると、イベント処理関数 ITIMECTL_HandleEvent に " ↑ " 、" ↓ " 、" ← " 、" → " のキーイベントを渡すことで時間が設定できます。

    //Active を FALSE に設定
    ITIMECTL_SetActive(app->_timectl, FALSE);

IDISPLAY インターフェースによる日付・時刻・曜日の表示

GETTIMESECONDS マクロ関数は 1980 年 1 月 6 日 00:00:00(グリニッジ標準時)から現地時刻までの秒数を返します。

GETJULIANDATE マクロ関数はその秒数とJulianType 構造体へのポインタを受け取り、JulianType 構造体に現在時刻を設定します。

JulianType 構造体には、年、月、日、時、分、秒、曜日の変数があります。それらの変数に設定された文字列を表示します。( AECHAR 型に変換します )

OnAppStop 関数

アプリの終了時、 ITimeCtl インスタンスを解放し、タイマーはキャンセルします。

// アプレットが終了したときに呼び出される。
static boolean OnAppStop(TimerApp* app)
{
    // 各種解放処理
    if (app->timectl != NULL) {
        ITIMECTL_Release(app->timectl);
    }
    ISHELL_CancelTimer(app->a.m_pIShell, (PFNNOTIFY)OnTimerExpired, app);
    return TRUE;
}

※ サンプルコードには記していませんが、通常、サスペンド時はタイマーをキャンセルし、レジューム時にはタイマーを再設定します。サスペンド時に ITimeCtl インスタンスを解放した場合は、レジューム時に ITimeCtl のインスタンスを再生成します。