前のページ次のページ上に戻るホーム SophiaFramework UNIVERSE 5.3

9.20. コントロール(基礎編)

コントロールは、 コンテナウィンドウ内に配置されるように設計されたレスポンダです。

すべてのコントロールは SFYControl クラスを継承し、 最大値・最小値・現在値を保持しています。 これらの値の表す意味はコントロールの種類により異なります。

具象コントロールはアプリ開発ですぐに使うことができる部品であり、 抽象コントロールはカスタマイズされたユーザー定義コントロールを作成するための起点(基底クラス)となります。

表 9.23. 具象コントロールの種類

クラス名 解説
SFZSingleTextLabelControl 単一行の編集不可能なテキストを表示するラベルコントロールです。
SFZSingleEditLabelControl 単一行の編集可能なテキストを表示するラベルコントロールです。
SFZMultipleTextLabelControl 複数行の編集不可能なテキストを表示するラベルコントロールです。
SFZMultipleEditLabelControl 複数行の編集可能なテキストを表示するラベルコントロールです。
SFZImageLabelControl イメージを表示するラベルコントロールです。
SFZSingleTextBoxControl 単一行の編集不可能なテキストを表示するボックスコントロールです。
SFZSingleEditBoxControl 単一行の編集可能なテキストを表示するボックスコントロールです。
SFZMultipleTextBoxControl 複数行の編集不可能なテキストを表示するボックスコントロールです。
SFZMultipleEditBoxControl 複数行の編集可能なテキストを表示するボックスコントロールです。
SFZImageBoxControl イメージを表示するボックスコントロールです。
SFZTextButtonControl テキストを表示するボタンコントロールです。
SFZImageButtonControl イメージを表示するボタンコントロールです。
SFZComboBoxControl コンボボックスコントロールです。
SFZListBoxControl リストボックスコントロールです。
SFZCheckboxControl チェックボックスコントロールです。
SFZRadiobuttonControl ラジオボタンコントロールです。
SFZTabControl タブコントロールです。
SFZTabPage タブコントロールのタブページです。
SFZWebBrowserControl 簡易ウェブブラウザコントロールです。
SFZScrollBarControl スクロールバーコントロールです。
SFZContainerScrollBarControl コンテナ専用スクロールバーコントロールです。
SFZSoftKeyControl ソフトキーコントロールです。
[Important] 重要

すべての具象コントロールにおいて、 SFYResponder::SetParent 関数、 SFYResponder::SetState 関数、 SFYResponder::SetRealBound 関数の呼び出しは必須です。

その他の関数の呼び出しは省略可能です。

表 9.24. 抽象コントロールの種類

クラス名 解説
SFYControl コントロールを表す抽象クラスです。
SFYLabelControl ラベルコントロールを表す抽象クラスです。
SFYBoxControl ボックスコントロールを表す抽象クラスです。
SFYButtonControl ボタンコントロールを表す抽象クラスです。
SFYCheckboxControl チェックボックスコントロールを表す抽象クラスです。
SFYRadiobuttonControl ラジオボタンコントロールを表す抽象クラスです。
SFYTabControl タブコントロールの抽象クラスです。
SFYScrollBarControl スクロールバーを表すコントロールの抽象クラスです。

9.20.1. 単一行の編集不可能なテキストを表示するラベルコントロール[SFZSingleTextLabelControl]

図 9.52. 動作例(左:操作不能モード、右:操作可能モード)

動作例(左:操作不能モード、右:操作可能モード)

単一行の編集不可能なテキストを表示するラベルコントロール(SFZSingleTextLabelControl)には、 操作可能状態に応じて、 操作可能モードと操作不能モードの 2 種類の使用方法があります。

操作可能モードでは(状態が操作可能であるとき)、コントロールをフォーカスすることができます。 そのとき、SFYLabelControl::SetOperateKey 関数で設定する操作キーを押下すると、 結果イベント [SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_OK, SFYControl::GetCurrentValue())] を受信します。 文字数が多くスクロールして表示する必要がある場合には、フォーカスされているときに自動的にスクロールを開始します。

[Note] 注意
この結果イベントは SFZSingleTextLabelControl::HandleOperateKey 関数内で発生します。

操作不能モードでは(状態が操作不能であるとき)、普通のラベルコントロールとして動作します。

参照: 状態 | 結果イベント[SFEVT_RESPONDER_RESULT]

例 9.88. 宣言

SFMTYPEDEFRESPONDER(USRWindow)
class USRWindow: public SFZWindow {
    SFMSEALRESPONDER(USRWindow)
    SFMRESPONDERINSTANTIATEFOUR(USRWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
private:
    SFZSingleTextLabelControlSmp _label;

    // ...(省略)...
private:
    SFCError Make(Void);

    // 操作可能モードで操作キー押下時の結果イベントを受信するハンドラ
    XANDLER_DECLARE_VOIDRESULT(OnResult)
};

例 9.89. 実装

SFCError USRWindow::Make(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // 単一行テキストラベルコントロールを作成する
    if ((_label = SFZSingleTextLabelControl::NewInstance(&error)) != null) {

        // 単一行テキストラベルコントロールの親を USRWindow に設定する
        error = _label->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // 操作可能モードで操作キー押下時の結果イベントを受信するハンドラを登録する
            // 操作不能モードの場合、呼び出されることがないためハンドラは登録しない
            error = _label->RegisterHandler(
                SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END),
                XANDLER_INTERNAL(OnResult)
            );
            if (error == SFERR_NO_ERROR) {

                // 表示するテキストを設定する
                // SFXWideString オブジェクトの設定 (※リソースファイルから設定することも可能)
                error = _label->SetText("hello world");
                if (error == SFERR_NO_ERROR) {

                    // 単一行テキストラベルコントロールの実領域を最適なサイズの矩形に設定する[始点は(10, 10)]
                    _label->SetRealBound(_label->GetSuitableBound().SetOrigin(10, 10));

                    // 操作可能モードの場合: すべての状態を true に設定する
                    _label->SetState(true, true, true, true);
                    // 操作不能モードの場合: 操作可能状態を false に設定する
                    // _label->SetState(true, true, false, false);
                }
            }
        }
    }

    return error;
}

// 操作可能モードで操作キー押下時の結果イベントを受信するハンドラの実装
XANDLER_IMPLEMENT_VOIDRESULT(USRWindow, OnResult, invoker, reason, result)
{
    // invoker には単一行テキストラベルコントロールが渡される
    // reason には SFP16_RESULT_OK が渡される
    // result には現在値が渡される [ 現在値 = GetCurrentValue() の戻り値 ]

    // ...(省略)...

    return;
}

9.20.2. 単一行の編集可能なテキストを表示するラベルコントロール[SFZSingleEditLabelControl]

図 9.53. 動作例(標準入力モード)

動作例(標準入力モード)

図 9.54. 動作例(パスワード入力モード)

動作例(パスワード入力モード)

単一行の編集可能なテキストを表示するラベルコントロール(SFZSingleEditLabelControl)には、 操作可能状態に応じて、 操作可能モードと操作不能モードの 2 種類の使用方法があります。

操作可能モードでは(状態が操作可能であるとき)、コントロールをフォーカスすることができます。 そのとき、SFYLabelControl::SetOperateKey 関数で設定する操作キーを押下すると、 テキスト入力画面に遷移します。 そして、テキスト入力終了時に、 結果イベント [テキスト入力が成功した場合は、SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_OK, SFYControl::GetCurrentValue())、 失敗した場合は SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_ERROR, エラー値)] を受信します。 文字数が多くスクロールして表示する必要がある場合には、 フォーカスされているときに自動的にスクロールを開始します。

[Note] 注意
この結果イベントは SFZSingleEditLabelControl::HandleOperateKey 関数内で発生します。

操作不能モードでは(状態が操作不能であるとき)、普通のラベルコントロールとして動作します。

[Caution] テキスト入力画面でサスペンドした場合(BREW 2.0 / 2.1 / 3.1)

BREW 2.0 / 2.1 / 3.1 では、 テキスト入力画面でサスペンドした場合、サスペンドしたときのテキスト入力画面の内容で一旦入力が確定します。 これは SophiaFramework UNIVERSE の仕様です。

参照: 状態 | 結果イベント[SFEVT_RESPONDER_RESULT]

例 9.90. 宣言

SFMTYPEDEFRESPONDER(USRWindow)
class USRWindow: public SFZWindow {
    SFMSEALRESPONDER(USRWindow)
    SFMRESPONDERINSTANTIATEFOUR(USRWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
private:
    SFZSingleEditLabelControlSmp _label;

    // ...(省略)...
private:
    SFCError Make(Void);

    // 操作可能モードでテキスト入力終了時の結果イベントを受信するハンドラ
    XANDLER_DECLARE_VOIDRESULT(OnResult)
};

例 9.91. 実装

SFCError USRWindow::Make(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // 単一行エディットラベルコントロールを作成する
    if ((_label = SFZSingleEditLabelControl::NewInstance(&error)) != null) {

        // 単一行エディットラベルコントロールの親を USRWindow に設定する
        error = _label->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // 操作可能モードでテキスト入力終了時の結果イベントを受信するハンドラを登録する
            // 操作不能モードの場合、呼び出されることがないためハンドラは登録しない
            error = _label->RegisterHandler(
                SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END),
                XANDLER_INTERNAL(OnResult)
            );
            if (error == SFERR_NO_ERROR) {

                // 数字入力モードを ON に設定する
                _label->SetInputMode(AEE_TM_NUMBERS);

                // パスワード入力モードを ON に設定する
                error = _label->SetPasswordMode(true);
                if (error == SFERR_NO_ERROR) {

                    // 表示するテキストを設定する
                    // SFXWideString オブジェクトの設定 (※リソースファイルから設定することも可能)
                    error = _label->SetText("0123456789");
                    if (error == SFERR_NO_ERROR) {

                        // 単一行エディットラベルコントロールの実領域を最適なサイズの矩形に設定する[始点は(10, 10)]
                        _label->SetRealBound(_label->GetSuitableBound().SetOrigin(10, 10));

                        // 操作可能モードの場合: すべての状態を true に設定する
                        _label->SetState(true, true, true, true);
                        // 操作不能モードの場合: 操作可能状態を false に設定する
                        // _label->SetState(true, true, false, false);
                    }
                }
            }
        }
    }

    return error;
}

// 操作可能モードでテキスト入力終了時の結果イベントを受信するハンドラの実装
XANDLER_IMPLEMENT_VOIDRESULT(USRWindow, OnResult, invoker, reason, result)
{
    SFXWideString text;

    // invoker には単一行エディットラベルコントロールが渡される
    // reason には SFP16_RESULT_OK または SFP16_RESULT_ERROR が渡される

    switch (reason) {

        case SFP16_RESULT_OK:
            // テキスト入力が正常に終了した場合、reason には SFP16_RESULT_OK が渡される
            // このとき、result には現在値が渡される [ 現在値 = GetCurrentValue() の戻り値 ]

            // 入力されたテキストを取得する
            text = _label->GetText();

            // 入力されたテキストをデバッグウィンドウに表示する
            TRACE("%S", text.GetCString());

            break;

        case SFP16_RESULT_ERROR:
            // テキスト入力が正常に終了した場合、reason には SFP16_RESULT_ERROR が渡される
            // このとき、result にはエラー値(SFCError 型)が渡される

            // ...(省略)...
            break;
    }

    return;
}

9.20.3. 複数行の編集不可能なテキストを表示するラベルコントロール[SFZMultipleTextLabelControl]

図 9.55. 動作例(左:操作不能モード、右:操作可能モード)

動作例(左:操作不能モード、右:操作可能モード)

複数行の編集不可能なテキストを表示するラベルコントロール(SFZMultipleTextLabelControl)には、 操作可能状態に応じて、 操作可能モードと操作不能モードの 2 種類の使用方法があります。

操作可能モードでは(状態が操作可能であるとき)、コントロールをフォーカスすることができます。 そのとき、SFYLabelControl::SetOperateKey 関数で設定する操作キーを押下すると、 結果イベント [SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_OK, SFYControl::GetCurrentValue())] を受信します。

[Note] 注意
この結果イベントは SFZMultipleTextLabelControl::HandleOperateKey 関数内で発生します。

行数が多くスクロールして表示する必要がある場合には、 SFZMultipleTextLabelControl::SetScrollDownKey / SFZMultipleTextLabelControl::SetScrollUpKey / SFZMultipleTextLabelControl::SetPageDownKey / SFZMultipleTextLabelControl::SetPageUpKey / SFZMultipleTextLabelControl::SetSnapDownKey / SFZMultipleTextLabelControl::SetSnapUpKey 関数で設定するスクロールキーを押下してスクロールできます。

操作不能モードでは(状態が操作不能であるとき)、普通のラベルコントロールとして動作します。

参照: 状態 | 結果イベント[SFEVT_RESPONDER_RESULT]

例 9.92. 宣言

SFMTYPEDEFRESPONDER(USRWindow)
class USRWindow: public SFZWindow {
    SFMSEALRESPONDER(USRWindow)
    SFMRESPONDERINSTANTIATEFOUR(USRWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
private:
    SFZMultipleTextLabelControlSmp _label;

    // ...(省略)...
private:
    SFCError Make(Void);

    // 操作可能モードで操作キー押下時の結果イベントを受信するハンドラ
    XANDLER_DECLARE_VOIDRESULT(OnResult)
};

例 9.93. 実装

SFCError USRWindow::Make(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // 複数行テキストラベルコントロールを作成する
    if ((_label = SFZMultipleTextLabelControl::NewInstance(&error)) != null) {

        // 複数行テキストラベルコントロールの親を USRWindow に設定する
        error = _label->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // 操作可能モードで操作キー押下時の結果イベントを受信するハンドラを登録する
            // 操作不能モードの場合、呼び出されることがないためハンドラは登録しない
            error = _label->RegisterHandler(
                SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END),
                XANDLER_INTERNAL(OnResult)
            );
            if (error == SFERR_NO_ERROR) {

                // 表示するテキストを設定する
                // SFXWideString オブジェクトの設定 (※リソースファイルから設定することも可能)
                error = _label->SetText("hello world\nabc\nxyz");
                if (error == SFERR_NO_ERROR) {

                    // 複数行テキストラベルコントロールの実領域を USRWindow を (10, 10) だけ Deflate した矩形領域に収まる最適なサイズの矩形に設定する[始点は(10, 10)]
                    _label->SetRealBound(_label->GetSuitableBound(GetLocalBound().Deflate(10, 10)));

                    // 操作可能モードの場合: すべての状態を true に設定する
                    _label->SetState(true, true, true, true);
                    // 操作不能モードの場合: 操作可能状態を false に設定する
                    // _label->SetState(true, true, false, false);
                }
            }
        }
    }

    return error;
}

// 操作可能モードで操作キー押下時の結果イベントを受信するハンドラの実装
XANDLER_IMPLEMENT_VOIDRESULT(USRWindow, OnResult, invoker, reason, result)
{
    // invoker には複数行テキストラベルコントロールが渡される
    // reason には SFP16_RESULT_OK が渡される
    // result には現在値が渡される [ 現在値 = GetCurrentValue() の戻り値 ]

    // ...(省略)...

    return;
}

9.20.4. 複数行の編集可能なテキストを表示するラベルコントロール[SFZMultipleEditLabelControl]

図 9.56. 動作例(標準入力モード)

動作例(標準入力モード)

図 9.57. 動作例(パスワード入力モード)

動作例(パスワード入力モード)

複数行の編集可能なテキストを表示するラベルコントロール(SFZMultipleEditLabelControl)には、 操作可能状態に応じて、 操作可能モードと操作不能モードの 2 種類の使用方法があります。

操作可能モードでは(状態が操作可能であるとき)、コントロールをフォーカスすることができます。 そのとき、SFYLabelControl::SetOperateKey 関数で設定する操作キーを押下すると、 テキスト入力画面に遷移します。 そして、テキスト入力終了時に、 結果イベント [テキスト入力が成功した場合は、SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_OK, SFYControl::GetCurrentValue())、 失敗した場合は SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_ERROR, エラー値)] を受信します。

[Note] 注意
この結果イベントは SFZMultipleEditLabelControl::HandleOperateKey 関数内で発生します。

行数が多くスクロールして表示する必要がある場合には、 SFZMultipleEditLabelControl::SetScrollDownKey / SFZMultipleEditLabelControl::SetScrollUpKey / SFZMultipleEditLabelControl::SetPageDownKey / SFZMultipleEditLabelControl::SetPageUpKey / SFZMultipleEditLabelControl::SetSnapDownKey / SFZMultipleEditLabelControl::SetSnapUpKey 関数で設定するスクロールキーを押下してスクロールできます。

操作不能モードでは(状態が操作不能であるとき)、普通のラベルコントロールとして動作します。

[Caution] テキスト入力画面でサスペンドした場合(BREW 2.0 / 2.1 / 3.1)

BREW 2.0 / 2.1 / 3.1 では、 テキスト入力画面でサスペンドした場合、サスペンドしたときのテキスト入力画面の内容で一旦入力が確定します。 これは SophiaFramework UNIVERSE の仕様です。

参照: 状態 | 結果イベント[SFEVT_RESPONDER_RESULT]

例 9.94. 宣言

SFMTYPEDEFRESPONDER(USRWindow)
class USRWindow: public SFZWindow {
    SFMSEALRESPONDER(USRWindow)
    SFMRESPONDERINSTANTIATEFOUR(USRWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
private:
    SFZMultipleEditLabelControlSmp _label;

    // ...(省略)...
private:
    SFCError Make(Void);

    // 操作可能モードでテキスト入力終了時の結果イベントを受信するハンドラ
    XANDLER_DECLARE_VOIDRESULT(OnResult)
};

例 9.95. 実装

SFCError USRWindow::Make(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // 複数行エディットラベルコントロールを作成する
    if ((_label = SFZMultipleEditLabelControl::NewInstance(&error)) != null) {

        // 複数行エディットラベルコントロールの親を USRWindow に設定する
        error = _label->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // 操作可能モードでテキスト入力終了時の結果イベントを受信するハンドラを登録する
            // 操作不能モードの場合、呼び出されることがないためハンドラは登録しない
            error = _label->RegisterHandler(
                SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END),
                XANDLER_INTERNAL(OnResult)
            );
            if (error == SFERR_NO_ERROR) {

                // 数字入力モードを ON に設定する
                _label->SetInputMode(AEE_TM_NUMBERS);

                // パスワード入力モードを ON に設定する
                error = _label->SetPasswordMode(true);
                if (error == SFERR_NO_ERROR) {

                    // 表示するテキストを設定する
                    // SFXWideString オブジェクトの設定 (※リソースファイルから設定することも可能)
                    error = _label->SetText("0123456789\n012\n789");
                    if (error == SFERR_NO_ERROR) {

                        // 複数行エディットラベルコントロールの実領域を USRWindow を (10, 10) だけ Deflate した矩形領域に収まる最適なサイズの矩形に設定する[始点は(10, 10)]
                        _label->SetRealBound(_label->GetSuitableBound(GetLocalBound().Deflate(10, 10)));

                        // 操作可能モードの場合: すべての状態を true に設定する
                        _label->SetState(true, true, true, true);
                        // 操作不能モードの場合: 操作可能状態を false に設定する
                        // _label->SetState(true, true, false, false);
                    }
                }
            }
        }
    }

    return error;
}

// 操作可能モードでテキスト入力終了時の結果イベントを受信するハンドラの実装
XANDLER_IMPLEMENT_VOIDRESULT(USRWindow, OnResult, invoker, reason, result)
{
    SFXWideString text;

    // invoker には複数行エディットラベルコントロールが渡される
    // reason には SFP16_RESULT_OK または SFP16_RESULT_ERROR が渡される

    switch (reason) {

        case SFP16_RESULT_OK:
            // テキスト入力が正常に終了した場合、reason には SFP16_RESULT_OK が渡される
            // このとき、result には現在値が渡される [ 現在値 = GetCurrentValue() の戻り値 ]

            // 入力されたテキストを取得する
            text = _label->GetText();

            // 入力されたテキストをデバッグウィンドウに表示する
            TRACE("%S", text.GetCString());

            break;

        case SFP16_RESULT_ERROR:
            // テキスト入力が正常に終了した場合、reason には SFP16_RESULT_ERROR が渡される
            // このとき、result にはエラー値(SFCError 型)が渡される

            // ...(省略)...
            break;
    }

    return;
}

9.20.5. イメージを表示するラベルコントロール[SFZImageLabelControl]

図 9.58. 動作例(左:操作不能モード、右:操作可能モード)

動作例(左:操作不能モード、右:操作可能モード)

イメージを表示するラベルコントロール(SFZImageLabelControl)には、 操作可能状態に応じて、 操作可能モードと操作不能モードの 2 種類の使用方法があります。

操作可能モードでは(状態が操作可能であるとき)、コントロールをフォーカスすることができます。 そのとき、SFYLabelControl::SetOperateKey 関数で設定する操作キーを押下すると、 結果イベント [SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_OK, SFYControl::GetCurrentValue())] を受信します。

[Note] 注意
この結果イベントは SFYLabelControl::HandleOperateKey 関数内で発生します。

操作不能モードでは(状態が操作不能であるとき)、普通のラベルコントロールとして動作します。

参照: 状態 | 結果イベント[SFEVT_RESPONDER_RESULT]

例 9.96. 宣言

SFMTYPEDEFRESPONDER(USRWindow)
class USRWindow: public SFZWindow {
    SFMSEALRESPONDER(USRWindow)
    SFMRESPONDERINSTANTIATEFOUR(USRWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
private:
    SFZImageLabelControlSmp _label;

    // ...(省略)...
private:
    SFCError Make(Void);

    // 操作可能モードで操作キー押下時の結果イベントを受信するハンドラ
    XANDLER_DECLARE_VOIDRESULT(OnResult)
};

例 9.97. 実装

SFCError USRWindow::Make(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // イメージラベルコントロールを作成する
    if ((_label = SFZImageLabelControl::NewInstance(&error)) != null) {

        // イメージラベルコントロールの親を USRWindow に設定する
        error = _label->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // 操作可能モードで操作キー押下時の結果イベントを受信するハンドラを登録する
            // 操作不能モードの場合、呼び出されることがないためハンドラは登録しない
            error = _label->RegisterHandler(
                SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END),
                XANDLER_INTERNAL(OnResult)
            );
            if (error == SFERR_NO_ERROR) {

                // 表示するイメージを設定する
                // SFBImage オブジェクトの設定 ( リソースファイルやファイルから設定可能 )
                error = _label->SetImage(SFXPath("resource.bar"), IMAGE_ID);
                if (error == SFERR_NO_ERROR) {

                    // イメージラベルコントロールの実領域を最適なサイズの矩形に設定する[始点は(10, 10)]
                    _label->SetRealBound(_label->GetSuitableBound().SetOrigin(10, 10));

                    // 操作可能モードの場合: すべての状態を true に設定する
                    _label->SetState(true, true, true, true);
                    // 操作不能モードの場合: 操作可能状態を false に設定する
                    // _label->SetState(true, true, false, false);
                }
            }
        }
    }

    return error;
}

// 操作可能モードで操作キー押下時の結果イベントを受信するハンドラの実装
XANDLER_IMPLEMENT_VOIDRESULT(USRWindow, OnResult, invoker, reason, result)
{
    // invoker にはイメージラベルコントロールが渡される
    // reason には SFP16_RESULT_OK が渡される
    // result には現在値が渡される [ 現在値 = GetCurrentValue() の戻り値 ]

    // ...(省略)...

    return;
}

9.20.6. 単一行の編集不可能なテキストを表示するボックスコントロール[SFZSingleTextBoxControl]

図 9.59. 動作例

動作例

単一行の編集不可能なテキストを表示するボックスコントロール(SFZSingleTextBoxControl)は、 SFYBoxControl::SetOperateKey 関数で設定する操作キーを押下すると、 結果イベント [SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_OK, SFYControl::GetCurrentValue())] を受信します。

[Note] 注意
この結果イベントは SFZSingleTextBoxControl::HandleOperateKey 関数内で発生します。

文字数が多くスクロールして表示する必要がある場合には、 フォーカスされているときに自動的にスクロールを開始します。

参照: 結果イベント[SFEVT_RESPONDER_RESULT]

例 9.98. 宣言

SFMTYPEDEFRESPONDER(USRWindow)
class USRWindow: public SFZWindow {
    SFMSEALRESPONDER(USRWindow)
    SFMRESPONDERINSTANTIATEFOUR(USRWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
private:
    SFZSingleTextBoxControlSmp _box;

    // ...(省略)...
private:
    SFCError Make(Void);

    // 操作キー押下時の結果イベントを受信するハンドラ
    XANDLER_DECLARE_VOIDRESULT(OnResult)
};

例 9.99. 実装

SFCError USRWindow::Make(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // 単一行テキストボックスコントロールを作成する
    if ((_box = SFZSingleTextBoxControl::NewInstance(&error)) != null) {

        // 単一行テキストボックスコントロールの親を USRWindow に設定する
        error = _box->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // 操作キー押下時の結果イベントを受信するハンドラを登録する
            error = _box->RegisterHandler(
                SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END),
                XANDLER_INTERNAL(OnResult)
            );
            if (error == SFERR_NO_ERROR) {

                // 表示するテキストを設定する
                // SFXWideString オブジェクトの設定 (※リソースファイルから設定することも可能)
                error = _box->SetText("hello world");
                if (error == SFERR_NO_ERROR) {

                    // 単一行テキストボックスコントロールの実領域を最適なサイズの矩形に設定する[始点は(10, 10)]
                    _box->SetRealBound(_box->GetSuitableBound().SetOrigin(10, 10));

                    // 単一行テキストボックスコントロールの状態を「可視+活性+操作可能+フォーカス」にまとめて設定する
                    _box->SetState(true, true, true, true);
                }
            }
        }
    }

    return error;
}

// 操作キー押下時の結果イベントを受信するハンドラの実装
XANDLER_IMPLEMENT_VOIDRESULT(USRWindow, OnResult, invoker, reason, result)
{
    // invoker には単一行テキストボックスコントロールが渡される
    // reason には SFP16_RESULT_OK が渡される
    // result には現在値が渡される [ 現在値 = GetCurrentValue() の戻り値 ]

    // ...(省略)...

    return;
}

9.20.7. 単一行の編集可能なテキストを表示するボックスコントロール[SFZSingleEditBoxControl]

図 9.60. 動作例(標準入力モード)

動作例(標準入力モード)

図 9.61. 動作例(パスワード入力モード)

動作例(パスワード入力モード)

単一行の編集可能なテキストを表示するボックスコントロール(SFZSingleEditBoxControl)は、 SFYBoxControl::SetOperateKey 関数で設定する操作キーを押下すると、 テキスト入力画面に遷移します。 そして、テキスト入力終了時に、 結果イベント [テキスト入力が成功した場合は、SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_OK, SFYControl::GetCurrentValue())、 失敗した場合は SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_ERROR, エラー値)] を受信します。

[Note] 注意
この結果イベントは SFZSingleEditBoxControl::HandleOperateKey 関数内で発生します。

文字数が多くスクロールして表示する必要がある場合には、 フォーカスされているときに自動的にスクロールを開始します。

[Caution] テキスト入力画面でサスペンドした場合(BREW 2.0 / 2.1 / 3.1)

BREW 2.0 / 2.1 / 3.1 では、 テキスト入力画面でサスペンドした場合、サスペンドしたときのテキスト入力画面の内容で一旦入力が確定します。 これは SophiaFramework UNIVERSE の仕様です。

参照: 結果イベント[SFEVT_RESPONDER_RESULT]

例 9.100. 宣言

SFMTYPEDEFRESPONDER(USRWindow)
class USRWindow: public SFZWindow {
    SFMSEALRESPONDER(USRWindow)
    SFMRESPONDERINSTANTIATEFOUR(USRWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
private:
    SFZSingleEditBoxControlSmp _box;

    // ...(省略)...
private:
    SFCError Make(Void);

    // 入力終了時の結果イベントを受信するハンドラ
    XANDLER_DECLARE_VOIDRESULT(OnResult)
};

例 9.101. 実装

SFCError USRWindow::Make(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // 単一行エディットボックスコントロールを作成する
    if ((_box = SFZSingleEditBoxControl::NewInstance(&error)) != null) {

        // 単一行エディットボックスコントロールの親を USRWindow に設定する
        error = _box->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // 入力終了時の結果イベントを受信するハンドラを登録する
            error = _box->RegisterHandler(
                SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END),
                XANDLER_INTERNAL(OnResult)
            );
            if (error == SFERR_NO_ERROR) {

                // 数字入力モードを ON に設定する
                _box->SetInputMode(AEE_TM_NUMBERS);

                // パスワード入力モードを ON に設定する
                error = _box->SetPasswordMode(true);
                if (error == SFERR_NO_ERROR) {

                    // 表示するテキストを設定する
                    // SFXWideString オブジェクトの設定 (※リソースファイルから設定することも可能)
                    error = _box->SetText("0123456789");
                    if (error == SFERR_NO_ERROR) {

                        // 単一行エディットボックスコントロールの実領域を最適なサイズの矩形に設定する[始点は(10, 10)]
                        _box->SetRealBound(_box->GetSuitableBound().SetOrigin(10, 10));

                        // 単一行エディットボックスコントロールの状態を「可視+活性+操作可能+フォーカス」にまとめて設定する
                        _box->SetState(true, true, true, true);
                    }
                }
            }
        }
    }

    return error;
}

// 入力終了時の結果イベントを受信するハンドラの実装
XANDLER_IMPLEMENT_VOIDRESULT(USRWindow, OnResult, invoker, reason, result)
{
    SFXWideString text;

    // invoker には単一行エディットボックスコントロールが渡される
    // reason には SFP16_RESULT_OK または SFP16_RESULT_ERROR が渡される

    switch (reason) {

        case SFP16_RESULT_OK:
            // テキスト入力が正常に終了した場合、reason には SFP16_RESULT_OK が渡される
            // このとき、result には現在値が渡される [ 現在値 = GetCurrentValue() の戻り値 ]

            // 入力されたテキストを取得する
            text = _box->GetText();

            // 入力されたテキストをデバッグウィンドウに表示する
            TRACE("%S", text.GetCString());

            break;

        case SFP16_RESULT_ERROR:
            // テキスト入力が正常に終了した場合、reason には SFP16_RESULT_ERROR が渡される
            // このとき、result にはエラー値(SFCError 型)が渡される

            // ...(省略)...
            break;
    }

    return;
}

9.20.8. 複数行の編集不可能なテキストを表示するボックスコントロール[SFZMultipleTextBoxControl]

図 9.62. 動作例

動作例

複数行の編集不可能なテキストを表示するボックスコントロール(SFZMultipleTextBoxControl)は、 SFYBoxControl::SetOperateKey 関数で設定する操作キーを押下すると、 結果イベント [SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_OK, SFYControl::GetCurrentValue())] を受信します。

[Note] 注意
この結果イベントは SFZMultipleTextBoxControl::HandleOperateKey 関数内で発生します。

行数が多くスクロールして表示する必要がある場合には、 SFZMultipleTextBoxControl::SetScrollDownKey / SFZMultipleTextBoxControl::SetScrollUpKey / SFZMultipleTextBoxControl::SetPageDownKey / SFZMultipleTextBoxControl::SetPageUpKey / SFZMultipleTextBoxControl::SetSnapDownKey / SFZMultipleTextBoxControl::SetSnapUpKey 関数で設定するスクロールキーを押下してスクロールできます。

参照: 結果イベント[SFEVT_RESPONDER_RESULT]

例 9.102. 宣言

SFMTYPEDEFRESPONDER(USRWindow)
class USRWindow: public SFZWindow {
    SFMSEALRESPONDER(USRWindow)
    SFMRESPONDERINSTANTIATEFOUR(USRWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
private:
    SFZMultipleTextBoxControlSmp _box;

    // ...(省略)...
private:
    SFCError Make(Void);

    // 操作キー押下時の結果イベントを受信するハンドラ
    XANDLER_DECLARE_VOIDRESULT(OnResult)
};

例 9.103. 実装

SFCError USRWindow::Make(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // 複数行テキストボックスコントロールを作成する
    if ((_box = SFZMultipleTextBoxControl::NewInstance(&error)) != null) {

        // 複数行テキストボックスコントロールの親を USRWindow に設定する
        error = _box->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // 操作キー押下時の結果イベントを受信するハンドラを登録する
            error = _box->RegisterHandler(
                SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END),
                XANDLER_INTERNAL(OnResult)
            );
            if (error == SFERR_NO_ERROR) {

                // 表示するテキストを設定する
                // SFXWideString オブジェクトの設定 (※リソースファイルから設定することも可能)
                error = _box->SetText("hello world\nabc\nxyz");
                if (error == SFERR_NO_ERROR) {

                    // 複数行テキストボックスコントロールの実領域を USRWindow を (10, 10) だけ Deflate した矩形領域に収まる最適なサイズの矩形に設定する[始点は(10, 10)]
                    _box->SetRealBound(_box->GetSuitableBound(GetLocalBound().Deflate(10, 10)));

                    // 複数行テキストボックスコントロールの状態を「可視+活性+操作可能+フォーカス」にまとめて設定する
                    _box->SetState(true, true, true, true);
                }
            }
        }
    }

    return error;
}

// 操作キー押下時の結果イベントを受信するハンドラの実装
XANDLER_IMPLEMENT_VOIDRESULT(USRWindow, OnResult, invoker, reason, result)
{
    // invoker には複数行テキストボックスコントロールが渡される
    // reason には SFP16_RESULT_OK が渡される
    // result には現在値が渡される [ 現在値 = GetCurrentValue() の戻り値 ]

    // ...(省略)...

    return;
}

9.20.9. 複数行の編集可能なテキストを表示するボックスコントロール[SFZMultipleEditBoxControl]

図 9.63. 動作例(標準入力モード)

動作例(標準入力モード)

図 9.64. 動作例(パスワード入力モード)

動作例(パスワード入力モード)

複数行の編集可能なテキストを表示するボックスコントロール(SFZMultipleEditBoxControl)は、 SFYBoxControl::SetOperateKey 関数で設定する操作キーを押下すると、 テキスト入力画面に遷移します。 そして、テキスト入力終了時に、 結果イベント [テキスト入力が成功した場合は、SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_OK, SFYControl::GetCurrentValue())、 失敗した場合は SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_ERROR, エラー値)] を受信します。

[Note] 注意
この結果イベントは SFZMultipleEditBoxControl::HandleOperateKey 関数内で発生します。

行数が多くスクロールして表示する必要がある場合には、 SFZMultipleEditBoxControl::SetScrollDownKey / SFZMultipleEditBoxControl::SetScrollUpKey / SFZMultipleEditBoxControl::SetPageDownKey / SFZMultipleEditBoxControl::SetPageUpKey / SFZMultipleEditBoxControl::SetSnapDownKey / SFZMultipleEditBoxControl::SetSnapUpKey 関数で設定するスクロールキーを押下してスクロールできます。

[Caution] テキスト入力画面でサスペンドした場合(BREW 2.0 / 2.1 / 3.1)

BREW 2.0 / 2.1 / 3.1 では、 テキスト入力画面でサスペンドした場合、サスペンドしたときのテキスト入力画面の内容で一旦入力が確定します。 これは SophiaFramework UNIVERSE の仕様です。

参照: 結果イベント[SFEVT_RESPONDER_RESULT]

例 9.104. 宣言

SFMTYPEDEFRESPONDER(USRWindow)
class USRWindow: public SFZWindow {
    SFMSEALRESPONDER(USRWindow)
    SFMRESPONDERINSTANTIATEFOUR(USRWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
private:
    SFZMultipleEditBoxControlSmp _box;

    // ...(省略)...
private:
    SFCError Make(Void);

    // 入力終了時の結果イベントを受信するハンドラ
    XANDLER_DECLARE_VOIDRESULT(OnResult)
};

例 9.105. 実装

SFCError USRWindow::Make(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // 複数行エディットボックスコントロールを作成する
    if ((_box = SFZMultipleEditBoxControl::NewInstance(&error)) != null) {

        // 複数行エディットボックスコントロールの親を USRWindow に設定する
        error = _box->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // 入力終了時の結果イベントを受信するハンドラを登録する
            error = _box->RegisterHandler(
                SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END),
                XANDLER_INTERNAL(OnResult)
            );
            if (error == SFERR_NO_ERROR) {

                // 数字入力モードを ON に設定する
                _box->SetInputMode(AEE_TM_NUMBERS);

                // パスワード入力モードを ON に設定する
                error = _box->SetPasswordMode(true);
                if (error == SFERR_NO_ERROR) {

                    // 表示するテキストを設定する
                    // SFXWideString オブジェクトの設定 (※リソースファイルから設定することも可能)
                    error = _box->SetText("0123456789\n012\n789");
                    if (error == SFERR_NO_ERROR) {

                        // 複数行エディットボックスコントロールの実領域を USRWindow を (10, 10) だけ Deflate した矩形領域に収まる最適なサイズの矩形に設定する[始点は(10, 10)]
                        _box->SetRealBound(_box->GetSuitableBound(GetLocalBound().Deflate(10, 10)));

                        // 複数行エディットボックスコントロールの状態を「可視+活性+操作可能+フォーカス」にまとめて設定する
                        _box->SetState(true, true, true, true);
                    }
                }
            }
        }
    }

    return error;
}

// 入力終了時の結果イベントを受信するハンドラの実装
XANDLER_IMPLEMENT_VOIDRESULT(USRWindow, OnResult, invoker, reason, result)
{
    SFXWideString text;

    // invoker には複数行エディットボックスコントロールが渡される
    // reason には SFP16_RESULT_OK または SFP16_RESULT_ERROR が渡される

    switch (reason) {

        case SFP16_RESULT_OK:
            // テキスト入力が正常に終了した場合、reason には SFP16_RESULT_OK が渡される
            // このとき、result には現在値が渡される [ 現在値 = GetCurrentValue() の戻り値 ]

            // 入力されたテキストを取得する
            text = _box->GetText();

            // 入力されたテキストをデバッグウィンドウに表示する
            TRACE("%S", text.GetCString());

            break;

        case SFP16_RESULT_ERROR:
            // テキスト入力が正常に終了した場合、reason には SFP16_RESULT_ERROR が渡される
            // このとき、result にはエラー値(SFCError 型)が渡される

            // ...(省略)...
            break;
    }

    return;
}

9.20.10. イメージを表示するボックスコントロール[SFZImageBoxControl]

図 9.65. 動作例

動作例

イメージを表示するボックスコントロール(SFZImageBoxControl)では、 SFYBoxControl::SetOperateKey 関数で設定する操作キーを押下すると、 結果イベント [SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_OK, SFYControl::GetCurrentValue())] を受信します。

[Note] 注意
この結果イベントは SFYBoxControl::HandleOperateKey 関数内で発生します。

参照: 結果イベント[SFEVT_RESPONDER_RESULT]

例 9.106. 宣言

SFMTYPEDEFRESPONDER(USRWindow)
class USRWindow: public SFZWindow {
    SFMSEALRESPONDER(USRWindow)
    SFMRESPONDERINSTANTIATEFOUR(USRWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
private:
    SFZImageBoxControlSmp _box;

    // ...(省略)...
private:
    SFCError Make(Void);

    // 操作キー押下時の結果イベントを受信するハンドラ
    XANDLER_DECLARE_VOIDRESULT(OnResult)
};

例 9.107. 実装

SFCError USRWindow::Make(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // イメージボックスコントロールを作成する
    if ((_box = SFZImageBoxControl::NewInstance(&error)) != null) {

        // イメージボックスコントロールの親を USRWindow に設定する
        error = _box->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // 操作キー押下時の結果イベントを受信するハンドラを登録する
            error = _box->RegisterHandler(
                SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END),
                XANDLER_INTERNAL(OnResult)
            );
            if (error == SFERR_NO_ERROR) {

                // 表示するイメージを設定する
                // SFBImage オブジェクトの設定 ( リソースファイルやファイルから設定可能 )
                error = _box->SetImage(SFXPath("resource.bar"), IMAGE_ID);
                if (error == SFERR_NO_ERROR) {

                    // イメージボックスコントロールの実領域を最適なサイズの矩形に設定する[始点は(10, 10)]
                    _box->SetRealBound(_box->GetSuitableBound().SetOrigin(10, 10));

                    // イメージボックスコントロールの状態を「可視+活性+操作可能+フォーカス」にまとめて設定する
                    _box->SetState(true, true, true, true);
                }
            }
        }
    }

    return error;
}

// 操作キー押下時の結果イベントを受信するハンドラの実装
XANDLER_IMPLEMENT_VOIDRESULT(USRWindow, OnResult, invoker, reason, result)
{
    // invoker にはイメージボックスコントロールが渡される
    // reason には SFP16_RESULT_OK が渡される
    // result には現在値が渡される [ 現在値 = GetCurrentValue() の戻り値 ]

    // ...(省略)...

    return;
}

9.20.11. テキストを表示するボタンコントロール[SFZTextButtonControl]

図 9.66. 動作例

動作例

テキストを表示するボタンコントロール(SFZTextButtonControl)は、 SFYButtonControl::SetOperateKey 関数で設定する操作キーを押下後に離すと、 結果イベント [SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_OK, SFYControl::GetCurrentValue())] を受信します。

[Note] 注意
この結果イベントは SFYButtonControl::HandleOperateKeyRelease 関数内で発生します。

文字数が多くスクロールして表示する必要がある場合には、 フォーカスされているときに自動的にスクロールを開始します。

参照: 結果イベント[SFEVT_RESPONDER_RESULT]

例 9.108. 宣言

SFMTYPEDEFRESPONDER(USRWindow)
class USRWindow: public SFZWindow {
    SFMSEALRESPONDER(USRWindow)
    SFMRESPONDERINSTANTIATEFOUR(USRWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
private:
    SFZTextButtonControlSmp _button;

    // ...(省略)...
private:
    SFCError Make(Void);

    // テキストボタンコントロール操作時の結果イベントを受信するハンドラ
    XANDLER_DECLARE_VOIDRESULT(OnResult)
};

例 9.109. 実装

SFCError USRWindow::Make(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // テキストボタンコントロールを作成する
    if ((_button = SFZTextButtonControl::NewInstance(&error)) != null) {

        // テキストボタンコントロールの親を USRWindow に設定する
        error = _button->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // テキストボタンコントロール操作時の結果イベントを受信するハンドラを登録する
            error = _button->RegisterHandler(
                SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END),
                XANDLER_INTERNAL(OnResult)
            );
            if (error == SFERR_NO_ERROR) {

                // 表示するテキストを設定する
                // SFXWideString オブジェクトの設定(※リソースファイルから設定することも可能)
                error = _button->SetText("hello world");
                if (error == SFERR_NO_ERROR) {

                    // テキストボタンコントロールの実領域を最適なサイズの矩形に設定する[始点は(10, 10)]
                    _button->SetRealBound(_button->GetSuitableBound().SetOrigin(10, 10));

                    // テキストボタンコントロールの状態を「可視+活性+操作可能+フォーカス」にまとめて設定する
                    _button->SetState(true, true, true, true);
                }
            }
        }
    }

    return error;
}

// テキストボタンコントロール操作時の結果イベントを受信するハンドラの実装
XANDLER_IMPLEMENT_VOIDRESULT(USRWindow, OnResult, invoker, reason, result)
{
    // invoker にはテキストボタンコントロールが渡される
    // reason には SFP16_RESULT_OK が渡される
    // result には現在値が渡される [ 現在値 = GetCurrentValue() の戻り値 ]

    // ...(省略)...

    return;
}

9.20.12. イメージを表示するボタンコントロール[SFZImageButtonControl]

図 9.67. 動作例

動作例

イメージを表示するボタンコントロール(SFZImageButtonControl)は、 SFYButtonControl::SetOperateKey 関数で設定する操作キーを押下後に離すと、 結果イベント [SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_OK, SFYControl::GetCurrentValue())] を受信します。

[Note] 注意
この結果イベントは SFYButtonControl::HandleOperateKeyRelease 関数内で発生します。

参照: 結果イベント[SFEVT_RESPONDER_RESULT]

例 9.110. 宣言

SFMTYPEDEFRESPONDER(USRWindow)
class USRWindow: public SFZWindow {
    SFMSEALRESPONDER(USRWindow)
    SFMRESPONDERINSTANTIATEFOUR(USRWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
private:
    SFZImageButtonControlSmp _button;

    // ...(省略)...
private:
    SFCError Make(Void);

    // イメージボタンコントロール操作時の結果イベントを受信するハンドラ
    XANDLER_DECLARE_VOIDRESULT(OnResult)
};

例 9.111. 実装

SFCError USRWindow::Make(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // イメージボタンコントロールを作成する
    if ((_button = SFZImageButtonControl::NewInstance(&error)) != null) {

        // イメージボタンコントロールの親を USRWindow に設定する
        error = _button->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // イメージボタンコントロール操作時の結果イベントを受信するハンドラを登録する
            error = _button->RegisterHandler(
                SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END),
                XANDLER_INTERNAL(OnResult)
            );
            if (error == SFERR_NO_ERROR) {

                // 表示するイメージを設定する
                // SFBImage オブジェクトの設定(リソースファイルやファイルから設定可能)
                error = _button->SetImage(SFXPath("resource.bar"), IMAGE_ID);
                if (error == SFERR_NO_ERROR) {

                    // イメージボタンコントロールの実領域を最適なサイズの矩形に設定する[始点は(10, 10)]
                    _button->SetRealBound(_button->GetSuitableBound().SetOrigin(10, 10));

                    // イメージボタンコントロールの状態を「可視+活性+操作可能+フォーカス」にまとめて設定する
                    _button->SetState(true, true, true, true);
                }
            }
        }
    }

    return error;
}

// イメージボタンコントロール操作時の結果イベントを受信するハンドラの実装
XANDLER_IMPLEMENT_VOIDRESULT(USRWindow, OnResult, invoker, reason, result)
{
    // invoker にはイメージボタンコントロールが渡される
    // reason には SFP16_RESULT_OK が渡される
    // result には現在値が渡される [ 現在値 = GetCurrentValue() の戻り値 ]

    // ...(省略)...

    return;
}

9.20.13. スクロールバーを表示するコントロール[SFZScrollBarControl]

図 9.68. 動作例

動作例

SFZScrollBarControl は、 スクロールバーコントロールを表すクラスです。

仮想領域実領域よりも大きい場合や、 リストボックスやメニューなどで実領域に表示可能な項目よりもたくさんの項目がある場合、 レスポンダはスクロールしてコンテンツ(内容)を表示します。

このようなレスポンダでは、 以下の手順でスクロールバーコントロール(SFZScrollBarControl)を装着することにより、 実領域に現在表示されているコンテンツに関するコンテンツ全体に対する相対的な位置関係(スクロールの状況)をスクロールバーコントロールに表示することができます。

[Note] 注意

スクロールバーを装着する対象となるレスポンダを『ターゲットレスポンダ』と呼んでいます。 また、ターゲットレスポンダの実領域に現在表示されているコンテンツを『表示コンテンツ』、 表示されていないものも含めたすべてのコンテンツを『全体コンテンツ』と呼んでいます。

  1. SFYResponder::SetRealBound 関数を呼び出してスクロールバーコントロールの実領域を設定します (ターゲットレスポンダは、スクロールバーコントロールの親レスポンダか姉妹レスポンダの関係になります)。
  2. SFYControl::SetMinimumValue 関数を呼び出して最小値(=全体コンテンツの始点)を設定します。 [通常、この関数呼び出しは省略されます。デフォルト値の 0 を使用します。]
  3. SFYControl::SetMaximumValue 関数を呼び出して最大値(=全体コンテンツの終点または項目数)を設定します。
  4. SFYControl::SetCurrentValue 関数を呼び出して現在値(=表示コンテンツの始点)を設定します。
  5. SFYScrollBarControl::SetPageValue 関数を呼び出してページサイズ(=表示コンテンツの幅または項目数)を設定します。
  6. スクロールバーイベント [SFEVT_RESPONDER_SCROLLBAR]を受信したときに、 スクロールできない状態になったときはスクロールバーコントロールの状態を活性状態から不可視状態に変更し、 逆の場合は、不可視状態から活性状態に変更します。
  7. スクロールバーコントロールのデザインは、 SFYScrollBarControl::SetBevelColor / SFYScrollBarControl::SetTrackColor / SFYScrollBarControl::SetArrowColor 関数を呼び出して変更します。
  8. スクロールバーコントロールの垂直方向と水平方向の配置は、 SFYScrollBarControl::SetOrientation 関数を呼び出して変更します。
  9. 『ページサイズ ≧ {(最大値) - (最小値)} 』の場合、 スクロール不能状態にあり、サムは描画されません。このとき、『サムの長さ=トラックの長さ』となります。
[Note] ターゲットレスポンダの最小値、最大値、現在値、ページサイズについて

多くのレスポンダでは、 全体コンテンツの始点と終点の座標で最小値と最大値、表示コンテンツ(=実領域)の始点と幅で現在値とページサイズを表現します (いずれもローカル領域の座標系。スクロール方向が水平の場合は X 座標、垂直の場合は Y 座標。最小値は常に 0 です)。

ターゲットレスポンダの実領域や仮想領域が変更された場合、 全体コンテンツの始点や終点、表示コンテンツの始点や幅も変更されますので、 スクロールバーコントロールの最小値、最大値、現在値、ページサイズも更新する必要があります。

例外: SFZListBoxControl クラスでは、 全体コンテンツの項目数で最大値、表示コンテンツの先頭項目のインデックスで現在位置、 表示コンテンツの項目数でページサイズを表現します(最小値は常に 0)。

[Note] スクロールバーイベントについて

スクロールバーコントロールは、 ターゲットレスポンダがスクロール可能な状態からスクロール不可能な状態、あるいはその逆になったとき、 スクロールバーイベント [SFEVT_RESPONDER_SCROLLBAR] [SFXEvent(SFEVT_RESPONDER_SCROLLBAR, SFP16_SCROLLBAR_ENABLE, 0)] を受信します。

[Note] スクロール可能性の判定について

ターゲットレスポンダが現在スクロール可能であるかどうかは、 SFYScrollBarControl::IsScrollable 関数を使用して判定します。

[Note] スクロールバーコントロールの幅について

スクロールバーコントロールの幅として、4 ピクセル以上の値を指定できます。 減分・増分矢印を矩形領域内にバランス良く描画するには、5 以上の奇数を指定することを推奨します。

[Note] Increment / Decrement / SetScrollStepValue 関数について

スクロールバーコントロールを装着するレスポンダ(ターゲットレスポンダ) 側でスクロールバーコントロールの現在値を増減する場合、 SFYScrollBarControl::Increment / SFYScrollBarControl::Decrement / SFYScrollBarControl::SetScrollStepValue 関数は使用しません。

これらの関数は、 スクロールバーコントロール側からターゲットレスポンダをスクロールしたい場合に使用します。

通常、ターゲットレスポンダ側でスクロールさせますので、 これらの関数を使用する機会は少ないと考えられます。

例 9.112. 宣言

SFMTYPEDEFRESPONDER(USRWindow)
class USRWindow: public SFZWindow {
    SFMSEALRESPONDER(USRWindow)
    SFMRESPONDERINSTANTIATEFOUR(USRWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
private:
    SFZContainerSmp _container;
    SFZScrollBarControlSmp _bar;

public:
    SFCError Make(Void);

    // ...
private:

    // コンテナの領域情報を読み取りスクロールバーのサムの位置と大きさを設定する関数
    Void Listen(SFYResponderPtr container);

    // コンテナの実領域と仮想領域に関する領域イベント用ハンドラ
    XANDLER_DECLARE_VOIDBOUND(OnContainerBound)
};

例 9.113. 実装

#define SCROLLBAR_WIDTH 5

SFCError USRWindow::Make(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // コンテナを作成する
    if ((_container = SFZContainer::NewInstance(&error)) != null) {

        // コンテナの親を USRWindow に設定する
        error = _container->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // 実領域と仮想領域に関する領域イベント用ハンドラをコンテナに登録する
            error = _container->RegisterHandler(
                SFXEventRange(SFEVT_RESPONDER_BOUND, SFEVT_RESPONDER_BOUND, SFP16_BOUND_REAL, SFP16_BOUND_VIRTUAL),
                XANDLER_INTERNAL(OnContainerBound)
            );

            if (error == SFERR_NO_ERROR) {

                // コンテナの背景色を設定する
                _container->SetBackgroundColor(SFXRGBColor(0xFF, 0xCC, 0xCC, 0x00));

                // コンテナの実領域をウィンドウのローカル領域からスクロールバーの分だけ除いた領域に設定する
                _container->SetRealBound(GetLocalBound().SubWidth(SCROLLBAR_WIDTH));

                // コンテナの仮想領域を実領域から上下に 100 ずつ広げた領域に設定する
                _container->SetVirtualBound(SFXRectangle(_container->GetRealBound()).Inflate(0, 100));

                // コンテナの状態を「可視+活性+操作可能+フォーカス」にまとめて設定する
                _container->SetState(true, true, true, true);
                if ((_bar = SFZScrollBarControl::NewInstance(&error)) != null) {

                    // スクロールバーの親を USRWindow に設定する
                    error = _bar->SetParent(GetThis());
                    if (error == SFERR_NO_ERROR) {

                        // コンテナの右横にスクロールバーを配置する
                        _bar->SetRealBound(GetLocalBound().SetX(_container->GetRealBound().GetRight()).SetWidth(SCROLLBAR_WIDTH));

                        // スクロールバーの状態を「可視+活性+操作不能+非フォーカス」にまとめて設定する
                        _bar->SetState(true, true, false, false);

                        // コンテナの領域情報を読み取りスクロールバーのサムの位置と大きさを設定する
                        Listen(_container.Get());
                    }
                }
            }
        }
    }

    return error;
}

// コンテナの領域情報を読み取りスクロールバーのサムの位置と大きさを設定する関数
Void USRWindow::Listen(SFYResponderPtr container)
{
    SFXRectangle rx;
    SFXRectangle vx;
    SInt16 max;
    SInt16 cur;
    SInt16 page;

    if (_bar != null & container != null) {

        // コンテナの実領域を取得する
        rx = container->GetRealBound();

        // コンテナの仮想領域を取得する
        vx = container->GetVirtualBound();

        if (_bar->GetOrientation() == SFYScrollBarControl::VERTICAL) {
            // スクロールの方向が垂直の場合

            // max の値を仮想領域の縦幅に設定する
            max = vx.GetHeight();

            // cur の値をローカル座標系における実領域の始点の Y 値に設定する
            cur = -vx.GetTop();

            // page の値を実領域の縦幅に設定する
            page = rx.GetHeight();
        }
        else {
            // スクロールの方向が水平の場合

            // max の値を仮想領域の横幅に設定する
            max = vx.GetWidth();

            // cur の値をローカル座標系における実領域の始点の X 値に設定する
            cur = -vx.GetLeft();

            // page の値を実領域の横幅に設定する
            page = rx.GetWidth();
        }

        // 最小値を設定する (この値は常に 0 である)
        _bar->SetMinimumValue(0);

        // 最大値を設定する (この値は仮想領域の横幅もしくは縦幅になる)
        _bar->SetMaximumValue(max);

        // 現在値を設定する (この値はローカル領域座標系における実領域の始点の X 値または Y 値になる)
        _bar->SetCurrentValue(cur);

        // ページサイズを設定する (この値は実領域の横幅もしくは縦幅になる)
        _bar->SetPageValue(page);
    }
}

// コンテナの実領域と仮想領域に関する領域イベント用ハンドラの実装
XANDLER_IMPLEMENT_VOIDBOUND(USRWindow, OnContainerBound, invoker, reason, bound)
{
    unused(reason);
    unused(bound);

    // invoker にはコンテナが渡される

    // コンテナの領域が変更されたときにスクロールバーのサムの位置と大きさ更新する
    Listen(invoker);
}

9.20.14. コンテナ専用のスクロールバーを表示するコントロール[SFZContainerScrollBarControl]

図 9.69. 動作例

動作例

SFZContainerScrollBarControl は、 SFYContainer を継承するレスポンダのスクロール状況を表示するためのコンテナ専用スクロールバーコントロールです。

スクロールバーコントロール(SFZContainerScrollBarControl)をレスポンダ (SFYContainer を継承するコンテナ)装着と着脱の手順は以下の通りです。

[Note] 注意

スクロールバーを装着する対象となるレスポンダを『ターゲットレスポンダ』と呼んでいます。

  1. SFYResponder::SetRealBound 関数を呼び出してスクロールバーコントロールの実領域を設定します (ターゲットレスポンダは、スクロールバーコントロールの親レスポンダか姉妹レスポンダの関係になります)。
  2. SFZContainerScrollBarControl::Bind 関数を呼び出してターゲットレスポンダにスクロールバーコントロールを装着します。 スクロールバーコントロール装着後は着脱するまでスクロールバーコントロールの最小値、最大値、現在値、ページサイズは自動的に設定・更新されます。
  3. スクロールバーコントロールのデザインは、 SFYScrollBarControl::SetBevelColor / SFYScrollBarControl::SetTrackColor / SFYScrollBarControl::SetArrowColor 関数を呼び出して変更します。
  4. スクロールバーコントロールの垂直方向と水平方向の配置は、 SFYScrollBarControl::SetOrientation 関数を呼び出して変更します。
  5. SFZContainerScrollBarControl::UnBind 関数を呼び出してターゲットレスポンダからスクロールバーコントロールを着脱します。 スクロールバーコントロールやターゲットレスポンダの状態が無効状態になった場合、 この関数は自動的に呼び出されます。
[Note] ターゲットレスポンダの最小値、最大値、現在値、ページサイズについて

全体コンテンツの始点と終点の座標で最小値と最大値、表示コンテンツ(=実領域)の始点と幅で現在値とページサイズを表現します (いずれもローカル領域の座標系。スクロール方向が水平の場合は X 座標、垂直の場合は Y 座標。最小値は常に 0 です)。

ターゲットレスポンダの実領域仮想領域が変更された場合、 全体コンテンツの始点や終点、表示コンテンツの始点や幅も変更されます。 SFZContainerScrollBarControl クラスでは、 SFZScrollBarControl クラスと異なり、 開発者はスクロールバーコントロールの最小値、最大値、現在値、ページサイズを管理する必要がありません。 この処理は、SFZContainerScrollBarControl クラス内で自動的に行われます。

具体的には、領域変更通知ハンドラである SFZContainerScrollBarControl::OnBindBound 関数内から呼び出される SFZContainerScrollBarControl::Listen 関数によって行われます。

詳細は、 SFZContainerScrollBarControl::Bind / SFZContainerScrollBarControl::UnBind 関数の内部実装コードを参照してください。

[Note] スクロールバーイベントについて

スクロールバーコントロールは、 ターゲットレスポンダがスクロール可能な状態からスクロール不可能な状態、あるいはその逆になったとき、 スクロールバーイベント [SFEVT_RESPONDER_SCROLLBAR] [SFXEvent(SFEVT_RESPONDER_SCROLLBAR, SFP16_SCROLLBAR_ENABLE, 0)] を受信します。

[Note] スクロール可能性の判定について

ターゲットレスポンダが現在スクロール可能であるかどうかは、 SFYScrollBarControl::IsScrollable 関数を使用して判定します。

[Note] SFZContainerScrollBarControl のターゲットレスポンダの種類

SFZContainerScrollBarControl は、 SFYContainer を継承するレスポンダに装着します。

具象レスポンダクラスとしては、 SFZContainerSFZWindowSFZTabPageSFZDialogSFZMessageDialogSFZQuestionDialog を挙げることができます。

例 9.114. 宣言

SFMTYPEDEFRESPONDER(USRWindow)
class USRWindow: public SFZWindow {
    SFMSEALRESPONDER(USRWindow)
    SFMRESPONDERINSTANTIATEFOUR(USRWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
private:
    SFZContainerSmp _container;
    SFZContainerScrollBarControlSmp _bar;

public:
    SFCError Make(Void);

    // ...(省略)...
};

例 9.115. 実装

#define SCROLLBAR_WIDTH 5

SFCError USRWindow::Make(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // コンテナを作成する
    if ((_container = SFZContainer::NewInstance(&error)) != null) {

        // コンテナの親を USRWindow に設定する
        error = _container->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // コンテナの背景色を設定する
            _container->SetBackgroundColor(SFXRGBColor(0xFF, 0xCC, 0xCC, 0x00));

            // コンテナの実領域をウィンドウのローカル領域からスクロールバーの分だけ除いた領域に設定する
            _container->SetRealBound(GetLocalBound().SubWidth(SCROLLBAR_WIDTH));

            // コンテナの仮想領域を実領域から上下に 100 ずつ広げた領域に設定する
            _container->SetVirtualBound(SFXRectangle(_container->GetRealBound()).Inflate(0, 100));

            // コンテナの状態を「可視+活性+操作可能+フォーカス」にまとめて設定する
            _container->SetState(true, true, true, true);
            if ((_bar = SFZContainerScrollBarControl::NewInstance(&error)) != null) {

                // スクロールバーの親を USRWindow に設定する
                error = _bar->SetParent(GetThis());
                if (error == SFERR_NO_ERROR) {

                    // コンテナの右横にスクロールバーを配置する
                    _bar->SetRealBound(GetLocalBound().SetX(_container->GetRealBound().GetRight()).SetWidth(SCROLLBAR_WIDTH));

                    // スクロールバーの状態を「可視+活性+操作不能+非フォーカス」にまとめて設定する
                    _bar->SetState(true, true, false, false);

                    // コンテナと関連付ける
                    _bar->Bind(_container);
                }
            }
        }
    }

    return error;
}

9.20.15. リストボックスコントロール[SFZListBoxControl]

図 9.70. 動作例

動作例

リストボックスコントロール(SFZListBoxControl)は、 リストの中からユーザーに項目を 1 つ選択させるためのコントロールです。

選択された項目はハイライト表示されます。

[Note] 注意
項目が無効状態であれば、選択できません。

項目を追加するには、SFZListBoxControl::Insert / SFZListBoxControl::InsertFirst / SFZListBoxControl::InsertLast 関数を使います。 項目を削除するには、SFZListBoxControl::Remove / SFZListBoxControl::RemoveFirst / SFZListBoxControl::RemoveLast 関数を使います。 SFZListBoxControl::Clear 関数を呼び出すと、すべての項目が削除されます。

SFZListBoxControl::SetUpKey 関数で設定された UP キー、または SFZListBoxControl::SetDownKey 関数で設定された DOWN キーを使用して選択項目を項目単位で移動できます。

選択項目が移動した場合は、 値イベント [SFXEvent(SFEVT_RESPONDER_VALUE, SFP16_VALUE_CURRENT, 選択された項目のインデックス)] を送信します。

[Note] 注意
この値イベントは、内部的に呼び出される SFYControl::SetCurrentValue 関数内で発生します。

SFZListBoxControl::SetItemEnable 関数により設定される有効フラグが "false" である項目は、 SFZListBoxControl::SetItemForeColor 関数および SFZListBoxControl::SetSelForeColor 関数で設定された色、 SFZListBoxControl::SetItemBackColor 関数で設定された色を基にして目立たない色が自動的に計算されて描画されます。 選択項目の背景だけは、常に SFZListBoxControl::SetSelBackColor 関数で設定された色で描画されます。 また、このコントロールの状態が非活性状態であるときは、 すべての項目が 有効フラグが "false" であるときと同じ処理で描画されます。

SFZListBoxControl::SetGridLineEnable 関数と SFZListBoxControl::SetGridLineColor 関数を使用してグリッド線を表示することも可能です。 項目内のマージンは SFZListBoxControl::SetListMargin 関数で設定します。

デフォルトの実装では、リストボックスコントロール[SFZListBoxControl]は 下記の結果イベント[SFEVT_RESPONDER_RESULT]を受信します。

開発者は、これらの結果イベントを受信するハンドラを登録できます。

操作キーは、SFYBoxControl::SetOperateKey 関数を使用して設定します。 デフォルトでは、セレクトキーが操作キーとして割り当てられています。

アクセスキーは、SFZListBoxControl::SetItemAccessKey 関数を使用して設定します。

ESCAPE キーは、SFZListBoxControl::SetEscapeKey 関数を使用して設定します。 デフォルトでは、クリアキーが ESCAPE キーとして割り当てられています。

[Caution] 注意
選択項目が SFZListBoxControl::SetItemEnable 関数により無効化("false" が設定)されているとき、 結果イベントは発生しません。
[Note] 注意
この結果イベントは SFZListBoxControl::HandleEscapeKey 関数内で発生します。

参照: 結果イベント[SFEVT_RESPONDER_RESULT] | SFYBoxControl::HandleOperateKey | SFZListBoxControl::HandleAccessKey | SFZListBoxControl::HandleEscapeKey

例 9.116. 宣言

SFMTYPEDEFRESPONDER(USRWindow)
class USRWindow: public SFZWindow {
    SFMSEALRESPONDER(USRWindow)
    SFMRESPONDERINSTANTIATEFOUR(USRWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
private:
    SFZListBoxControlSmp _listbox;

    // ...(省略)...
private:
    SFCError Make(Void);

    // 結果イベントを受信するハンドラ
    XANDLER_DECLARE_VOIDRESULT(OnResult)
};

例 9.117. 実装

SFCError USRWindow::Make(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // リストボックスコントロールを作成する
    if ((_listbox = SFZListBoxControl::NewInstance(&error)) != null) {

        // リストボックスコントロールの親を USRWindow に設定する
        error = _listbox->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // 結果イベントを受信するハンドラを登録する
            error = _listbox->RegisterHandler(
                SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END),
                XANDLER_INTERNAL(OnResult)
            );
            if (error == SFERR_NO_ERROR) {

                for (SInt32 i = 0; i < 20; ++i) {

                    // 項目を追加する
                    error = _listbox->InsertLast(SFXWideString::Format("Item index is %d", i));

                    if (error != SFERR_NO_ERROR) break;
                }
                if (error == SFERR_NO_ERROR) {

                    // リストボックスコントロールの実領域を最適なサイズの矩形に設定する[始点は(20, 20)]
                    _listbox->SetRealBound(_listbox->GetSuitableBound(GetLocalBound().Deflate(20, 20)).SetOrigin(20, 20));

                    // リストボックスコントロールの状態を「可視+活性+操作可能+フォーカス」にまとめて設定する
                    _listbox->SetState(true, true, true, true);
                }
            }
        }
    }

    return error;
}

// リストボックスコントロール操作時の結果イベントを受信するハンドラの実装
XANDLER_IMPLEMENT_VOIDRESULT(USRWindow, OnResult, invoker, reason, result)
{
    SFXWideString text;

    // invoker にはリストボックスコントロールが渡される
    // reason には SFP16_RESULT_OK または SFP16_RESULT_ESCAPE が渡される

    switch (reason) {

        case SFP16_RESULT_OK:  
            // 操作キー押下時、reason には SFP16_RESULT_OK が渡される
            // このとき、result には現在値(選択された項目インデックス値)が渡される [ 現在値 = GetCurrentValue() の戻り値 ]

            // 選択された項目のテキストを取得する
            text = _listbox->GetItemText(result);

            // 選択された項目のテキストをデバッグウィンドウに表示する
            TRACE("%S", text.GetCString());

            break;

        case SFP16_RESULT_ESCAPE:
            // ESCAPE キー押下時、reason には SFP16_RESULT_ESCAPE が渡される
            // このとき、result には 0 が渡される

            // ...(省略)...
            break;
    }
    return;
}

9.20.16. コンボボックスコントロール[SFZComboBoxControl]

図 9.71. 動作例

動作例

コンボボックスコントロール(SFZComboBoxControl)は、 項目リストを表示するためのフレックスリストボックスコントロール(SFZFlexListBoxControl)を内部に保持するボタンコントロールです。

項目を追加するには、 SFZComboBoxControl::Insert / SFZComboBoxControl::InsertFirst / SFZComboBoxControl::InsertLast 関数を使います。 項目を削除するには、 SFZComboBoxControl::Remove / SFZComboBoxControl::RemoveFirst / SFZComboBoxControl::RemoveLast 関数を使います。 SFZComboBoxControl::Clear 関数を呼び出すと、すべての項目が削除されます。

フレックスリストボックスコントロール(SFZFlexListBoxControl)の部分は、 SFYButtonControl::SetOperateKey 関数で設定するコンボボックスコントロール(SFZComboBoxControl)の操作キーを押下後に離すと開きます。

コンボボックスコントロールの領域には、 このフレックスリストボックスコントロール内で現在選択されている項目が表示されます。

フレックスリストボックスコントロールでは、 フォーカスされた項目はハイライト表示されます。 SFZFlexListBoxControl::SetScrollUpKey / SFZFlexListBoxControl::SetScrollDownKey / SFZFlexListBoxControl::SetPageUpKey / SFZFlexListBoxControl::SetPageDownKey / SFZFlexListBoxControl::SetSnapUpKey / SFZFlexListBoxControl::SetSnapDownKey 関数で設定するスクロールキーを使用して項目リストをスクロールします。

  1. フレックスリストボックスコントロールが開いている状態で リスト内のある項目を選択して操作キーまたはアクセスキーを押下すると、 フレックスリストボックスコントロールが閉じます。 そして、選択した項目がコンボボックスコントロールに表示されます。 [前提条件: 選択項目が SFZFlexListBoxControl::SetItemEnable 関数により有効化("true" が設定)されている必要があります。]

    このとき、コンボボックスコントロールは 結果イベント [SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_OK, 選択した項目のインデックス)] を受信します。

    [Tip] Tip
    操作キーは、SFYBoxControl::SetOperateKey 関数を使用して設定します。 デフォルトでは、セレクトキーが操作キーとして割り当てられています。
    [Tip] Tip
    アクセスキーは、SFZFlexListBoxControl::SetItemAccessKey 関数を使用して設定します。
    [Caution] 注意
    選択項目が SFZFlexListBoxControl::SetItemEnable 関数により無効化("false" が設定)されているとき、 操作キーまたはアクセスキーを押しても何も起こりません。
  2. フレックスリストボックスコントロールが開いている状態で ESCAPE キーを押下すると、フレックスリストボックスコントロールが閉じます。 コンボボックスコントロールの内容はフレックスリストボックスコントロールが開く以前と同じです。

    [Tip] Tip
    ESCAPE キーは、SFZFlexListBoxControl::SetEscapeKey 関数を使用して設定します。 デフォルトでは、クリアキーが ESCAPE キーとして割り当てられています。
    [Caution] 注意
    この場合、コンボボックスコントロールで結果イベントは発生しません。
[Caution] 注意

コンボボックスコントロールに内部的に保持されるフレックスリストボックスコントロールの領域は、 追加された項目とコンボボックスコントロールが配置される親レスポンダのローカル領域によって自動的に設定されます。

フレックスリストボックスコントロールを描画するには、 SFYResponder::SetRealBound 関数を使用して親レスポンダの実領域(ローカル領域)の設定が必須になります。

親レスポンダの実領域は、 SFYResponder::SetVirtualBound 関数で仮想領域を設定しない限りローカル領域と同じです。

※ローカル領域と仮想領域は同じ矩形領域を表します。

例 9.118. 宣言

SFMTYPEDEFRESPONDER(USRWindow)
class USRWindow: public SFZWindow {
    SFMSEALRESPONDER(USRWindow)
    SFMRESPONDERINSTANTIATEFOUR(USRWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
private:
    SFZComboBoxControlSmp _combobox;

    // ...
private:
    SFCError Make(Void);

    // 結果イベント用ハンドラ
    XANDLER_DECLARE_VOIDRESULT(OnResult)
};

例 9.119. 実装

SFCError USRWindow::Make(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // コンボボックスコントロールを作成する
    if ((_combobox = SFZComboBoxControl::NewInstance(&error)) != null) {

        // コンボボックスコントロールの親を USRWindow に設定する
        error = _combobox->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // コンボボックスコントロールに結果ハンドラを登録する
            error = _combobox->RegisterHandler(
                SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END),
                XANDLER_INTERNAL(OnResult)
            );
            if (error == SFERR_NO_ERROR) {

                for (SInt32 i = 0; i < 10; ++i) {

                    // コンボボックスコントロールが内部的に保持するフレックスリストボックスコントロールに項目を追加する
                    error = _combobox->InsertLast(SFXWideString::Format("Item index is %d.", i));

                    if (error != SFERR_NO_ERROR) break;
                }
                if (error == SFERR_NO_ERROR) {

                    // コンボボックスコントロールの実領域を最適なサイズの矩形に設定する[始点は(20, 20)]
                    _combobox->SetRealBound(_combobox->GetSuitableBound(GetLocalBound().Deflate(20, 20)).SetOrigin(20, 20));

                    // コンボボックスコントロールの状態を「可視+活性+操作可能+フォーカス」にまとめて設定する
                    _combobox->SetState(true, true, true, true);
                }
            }
        }
    }

    return error;
}

// コンボボックスコントロールの結果ハンドラの実装
// ※このハンドラは、SetCurrentValue 関数で値を変更した場合は呼び出されない
XANDLER_IMPLEMENT_VOIDRESULT(USRWindow, OnResult, invoker, reason, result)
{
    SFXWideString text;

    // invoker にはコンボボックスコントロールが渡される
    // reason には SFP16_RESULT_OK が渡される
    // result には現在値(選択された項目インデックス値)が渡される [ 現在値 = GetCurrentValue() の戻り値 ]

    // 選択された項目のテキストを取得する
    text = _combobox->GetItemText(result);

    // 選択された項目のテキストをデバッグウィンドウに表示する
    TRACE("%S", text.GetCString());

    return;
}

9.20.17. チェックボックスコントロール[SFZCheckboxControl]

図 9.72. 動作例

動作例

チェックボックスコントロール(SFZCheckboxControl)は、 SFYButtonControl::SetOperateKey 関数で設定する操作キーを押下後に離すと、 結果イベント [SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_OK, SFYControl::GetCurrentValue())] を受信します。

[Note] 注意
この結果イベントは SFYCheckboxControl::HandleOperateKeyRelease 関数内で発生します。

文字数が多くスクロールして表示する必要がある場合には、 フォーカスされているときに自動的にスクロールを開始します。

参照: 結果イベント[SFEVT_RESPONDER_RESULT]

例 9.120. 宣言

SFMTYPEDEFRESPONDER(USRWindow)
class USRWindow: public SFZWindow {
    SFMSEALRESPONDER(USRWindow)
    SFMRESPONDERINSTANTIATEFOUR(USRWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
private:
    SFZCheckboxControlSmp _checkbox;

    // ...(省略)...
private:
    SFCError Make(Void);

    // チェックボックスコントロール操作時の結果イベントを受信するハンドラ
    XANDLER_DECLARE_VOIDRESULT(OnResult)
};

例 9.121. 実装

SFCError USRWindow::Make(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // チェックボックスコントロールを作成する
    if ((_checkbox = SFZCheckboxControl::NewInstance(&error)) != null) {

        // チェックボックスコントロールの親を USRWindow に設定する
        error = _checkbox->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // チェックボックスコントロール操作時の結果イベントを受信するハンドラを登録する
            error = _checkbox->RegisterHandler(
                SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END),
                XANDLER_INTERNAL(OnResult)
            );
            if (error == SFERR_NO_ERROR) {

                // 表示するテキストを設定する
                // SFXWideString オブジェクトの設定 (※リソースファイルから設定することも可能)
                error = _checkbox->SetText("hello world");
                if (error == SFERR_NO_ERROR) {

                    // チェックボックスコントロールの状態をチェックされている状態に設定する
                    _checkbox->SetCurrentValue(true);

                    // チェックボックスコントロールの実領域を最適なサイズの矩形に設定する[始点は(10, 10)]
                    _checkbox->SetRealBound(_checkbox->GetSuitableBound().SetOrigin(10, 10));

                    // チェックボックスコントロールの状態を「可視+活性+操作可能+フォーカス」にまとめて設定する
                    _checkbox->SetState(true, true, true, true);
                }
            }
        }
    }

    return error;
}

// チェックボックスコントロール操作時の結果イベントを受信するハンドラの実装
XANDLER_IMPLEMENT_VOIDRESULT(USRWindow, OnResult, invoker, reason, result)
{
    // invoker にはチェックボックスコントロールが渡される
    // reason には SFP16_RESULT_OK が渡される
    // result には現在値が渡される [ 現在値 = GetCurrentValue() の戻り値 ]

    // ...(省略)...

    return;
}

9.20.18. ラジオボタンコントロール[SFZRadiobuttonControl]

図 9.73. 動作例

動作例

ラジオボタンコントロール(SFZRadiobuttonControl)は、 SFYButtonControl::SetOperateKey 関数で設定する操作キーを押下後に離すと、 結果イベント [SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_OK, SFYControl::GetCurrentValue())] を受信します。

[Note] 注意
この結果イベントは SFYRadiobuttonControl::HandleOperateKeyRelease 関数内で発生します。

文字数が多くスクロールして表示する必要がある場合には、 フォーカスされているときに自動的にスクロールを開始します。

複数のラジオボタンコントロールをグループ化して、 排他的な選択処理を自動的に行うことができます。

参照: 結果イベント[SFEVT_RESPONDER_RESULT]

例 9.122. 宣言

SFMTYPEDEFRESPONDER(USRWindow)
class USRWindow: public SFZWindow {
    SFMSEALRESPONDER(USRWindow)
    SFMRESPONDERINSTANTIATEFOUR(USRWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
private:
    SFZRadiobuttonControlSmp _radiobutton;

    // ...(省略)...
private:
    SFCError Make(Void);

    // ラジオボタンコントロール操作時の結果イベントを受信するハンドラ
    XANDLER_DECLARE_VOIDRESULT(OnResult)
};

例 9.123. 実装

SFCError USRWindow::Make(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // ラジオボタンコントロールを作成する
    if ((_radiobutton = SFZRadiobuttonControl::NewInstance(&error)) != null) {

        // ラジオボタンコントロールの親を USRWindow に設定する
        error = _radiobutton->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // ラジオボタンコントロール操作時の結果イベントを受信するハンドラを登録する
            error = _radiobutton->RegisterHandler(
                SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END),
                XANDLER_INTERNAL(OnResult)
            );
            if (error == SFERR_NO_ERROR) {

                // 表示するテキストを設定する
                // SFXWideString オブジェクトの設定 (※リソースファイルから設定することも可能)
                error = _radiobutton->SetText("hello world");
                if (error == SFERR_NO_ERROR) {

                    // ラジオボタンコントロールの状態をチェックされている状態に設定する
                    _radiobutton->SetCurrentValue(true);

                    // ラジオボタンコントロールの実領域を最適なサイズの矩形に設定する[始点は(10, 10)]
                    _radiobutton->SetRealBound(_radiobutton->GetSuitableBound().SetOrigin(10, 10));

                    // ラジオボタンコントロールの状態を「可視+活性+操作可能+フォーカス」にまとめて設定する
                    _radiobutton->SetState(true, true, true, true);
                }
            }
        }
    }

    return error;
}

// ラジオボタンコントロール操作時の結果イベントを受信するハンドラの実装
XANDLER_IMPLEMENT_VOIDRESULT(USRWindow, OnResult, invoker, reason, result)
{
    // invoker にはラジオボタンコントロールが渡される
    // reason には SFP16_RESULT_OK が渡される
    // result には現在値が渡される [ 現在値 = GetCurrentValue() の戻り値 ]

    // ...(省略)...

    return;
}

9.20.19. タブコントロールとタブページ[SFZTabControl と SFZTabPage]

図 9.74. 動作例

動作例

タブコントロール(SFZTabControl)は、 複数のタブページ(SFZTabPage)をタブ形式のユーザーインターフェースで管理する機能を提供します。

タブコントロールへのタブページの挿入は、 タブページの親レスポンダをタブコントロールに設定することにより行います。

タブページの表示切り替えは、タブコントロールのタブのフォーカス移動によって行います。

SFZTabControl のレイアウト

タブページの追加

タブコントロールへのタブページの追加は、 タブページの SFYResponder::SetParent 関数を呼び出して親レスポンダにタブコントロールを設定することにより行います。

[Note] 注意

タブページは、タブコントロールに追加された順に並びます。 この順序を変更するには、タブページを削除して追加しなおす必要があります。

なお、タブページのインデックスは、タブページがタブコントロールに追加された順を表します。

[Note] 注意

コントロールは子レスポンダとしてコンテナ(SFYContainer クラスを継承するレスポンダ)を持ちませんが、 タブコントロールだけは例外的に子レスポンダとしてコンテナを持ちます。

領域の設定

SFYResponder::SetRealBound 関数を呼び出してタブコントロールの実領域を設定します。

[Note] 注意

内部処理により、 タブコントロールの仮想領域は、 常に実領域に一致します。

タブページの実領域は、 内部処理により自動的にタブコントロールのコンテント領域に設定されます。 開発者はタブページの実領域を設定する必要はありません。

[Note] タブコントロールのコンテント領域

タブコントロールのコンテント領域とは、 タブコントロールの領域からヒント領域、タブ領域、ボーダー領域、スクロールバー領域を除いた矩形領域のことです。 タブページの内容が表示される領域であるので、コンテント領域と呼びます。

タブページの仮想領域は、 タブコントロールにすべてのタブページを追加し終えてから一度だけ 明示的に SFYTabControl::AdjustPages 関数を呼び出すことにより行います。 このとき、仮想領域は自動的に計算されて、 タブコントロールのコンテント領域とタブページの子レスポンダを含む最小の矩形領域に設定されます (始点は (0, 0) で、タブページの実領域の始点と同じ)。

[Note] 注意

タブページのすべての子レスポンダがタブコントロールのコンテント領域内に配置される場合、 SFYTabControl::AdjustPages 関数の呼び出しは省略できます。

状態について

タブコントロールは、 以下のようにタブページの状態に応じて描画や、 フォーカス時の振る舞いが異なります。

  1. タブページが不可視状態の時、 ラベルはタブコントロール内に描画されません。 また、タブページの内容もコンテント領域に描画されません。
  2. タブページが可視状態かつ不活性状態の時、 ラベルはタブ領域に不活性状態で描画されますが、ラベルにフォーカスは移動しません。 そのため、タブページの内容はコンテント領域に描画されません。
  3. タブページが活性状態かつ操作不能状態の時、 ラベルはタブ領域に通常通りに描画されますが、ラベルにフォーカスは移動しません。 そのため、タブページの内容はコンテント領域に描画されません。
  4. タブページが操作可能状態の時、 ラベルはタブ領域に通常通りに描画されますが、ラベルにフォーカスは移動できます。 ラベルにフォーカスが移動したとき、タブページの内容はコンテント領域に描画されます。
[Note] 注意

上記のラベルとは、タブコントロールのタブに表示されるタブページのタイトルラベルのことです。

[Note] タブページの初期状態

インスタンス生成直後、タブページの状態は「可視+活性+操作可能+非フォーカス」に初期化されます。

大抵の場合は、この設定で十分なので、タブページの状態を設定する必要はありません。

[Caution] 注意

選択されたタブページは、 フォーカス状態は "true"に設定され、 同じ姉妹タブページの中で最前面に配置されます。

タブコントロールの表示内容の整合性が崩れるので、 タブページに対して SFYResponder::ToFront / SFYResponder::SetStateFocus 関数を呼び出すことは禁止されています。 タブページの内容を表示する場合は、SFYTabControl::FocusPage 関数を使用してください。

タブコントロールのデザイン

タブ領域やヒント領域、ボーダー領域を表示するための関数が利用可能です。 詳しくは、SFZTabControl / SFZTabPage クラスのリファレンスを参照してください。

タブページの選択

タブコントロールには、SFYTabControl::SetFieldValue 関数で設定した数のタブが表示されます。

各タブには対応するタブページが存在し、タブには対応するタブページのタイトルテキストが表示されます (ヒント領域が設定されている場合はヒントテキストも表示されます)。 そのうちの 1 つのタブページだけがフォーカス状態になり、その内容がコンテント領域に表示されます。

SFZTabControl::SetFocusTabTopEdgeEnable 関数で上境界線を有効に設定している場合、 フォーカス状態のタブページに対応するタブの上境界線は SFZTabControl::SetFocusTabTopEdgeColor 関数で設定した色で描画されます。

特定のタブページにフォーカスを移動するには、 SFYTabControl::FocusPage 関数を呼び出します。 現在フォーカスを持つタブページのフォーカスを前後(左右)のタブページに移動するには、 SFYTabControl::FocusLeft / SFYTabControl::FocusRight 関数を呼び出します。

フォーカスの移動先であるタブページのタイトルテキストがタブコントロールのタブ領域に表示されていない場合は、 自動的にタブ領域が左右にスクロールして表示されます。

[Note] 注意

SFYTabControl::FocusLeft / SFYTabControl::FocusRight 関数は、 SFYTabControl::SetFocusLeftKey / SFYTabControl::SetFocusRightKey 関数で設定した左右のフォーカス移動キーを押下すると呼び出されます。

[Caution] 注意

選択されたタブページは、 フォーカス状態は "true"に設定され、 同じ姉妹タブページの中で最前面に配置されます。

タブコントロールの表示内容の整合性が崩れるので、 タブページに対して SFYResponder::ToFront / SFYResponder::SetStateFocus 関数を呼び出すことは禁止されています。 タブページの内容を表示する場合は、SFYTabControl::FocusPage 関数を使用してください。

タブページの削除

タブコントロールからタブページを削除する方法は以下の通りです。

タブコントロールからタブページを動的に削除するコードは以下の通りです。

// CASE 1. タブページを保持する場合 (親を空にする)
page->SetParent(SFYResponder::EmptyInstance());

// CASE 2. タブページを他のタブコントロールで利用する場合(親を他のタブコントロールに設定する)
SFYTabControlSmp othertab;
page->SetParent(othertab);

// CASE 3. タブページを破棄する場合
page->Terminate();

例 9.124. 宣言

SFMTYPEDEFRESPONDER(USRWindow)
class USRWindow: public SFZWindow {
    SFMSEALRESPONDER(USRWindow)
    SFMRESPONDERINSTANTIATEFOUR(USRWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
private:
    SFZTabControlSmp _tab;

    // ...(省略)...
private:
    SFCError Make(Void);
};

例 9.125. 実装

SFCError USRWindow::Make(Void)
{
    SFBShellSmp shell;
    SFBImageSmp image;
    SFXWideString text;
    SFZTabPageSmp page[4];
    SFZTextButtonControlSmp button[4];
    SFXRectangle rectangle;
    SInt16 i;
    SFCError error(SFERR_NO_ERROR);

    // タブコントロールを作成する
    if ((_tab = SFZTabControl::NewInstance(&error)) != null) {

        // タブコントロールの親を USRWindow に設定する
        error = _tab->SetParent(GetThis());

        if (error == SFERR_NO_ERROR) {

            // タブコントロールの実領域を USRWindow のローカル領域に設定する
            _tab->SetRealBound(GetLocalBound());

            // タブコントロールの背景色を設定する
            _tab->SetBackgroundColor(SFXRGBColor(0xDD, 0xFF, 0xDD, 0x00));

            // タブコントロール領域に 3 つのタブページが表示されるように設定する
            _tab->SetFieldValue(3);

            // タブコントロールの状態を「可視+活性+操作可能+フォーカス」にまとめて設定する
            _tab->SetState(true, true, true, true);

            // SFBShell インスタンスを取得する
            shell = SFBShell::GetInstance();

            if (shell != null) {

                // 4 ページ分のタブページを作成した後、追加する
                for (i = 0; i < 4; ++ i) {

                    // タブページを作成する
                    page[i] = SFZTabPage::NewInstance(&error);
                    if (page[i] != null) {

                        // タブコントロールをタブページの親レスポンダにする
                        // タブページの実領域が自動的に設定される
                        error = page[i]->SetParent(_tab);

                        if (error == SFERR_NO_ERROR) {

                            // タブページのタイトルテキストを設定する
                            text = SFXWideString::Format("%c", 'A' + i);
                            page[i]->SetTitle(text);

                            // タブページのヒントテキストを設定する
                            text = SFXWideString::Format("Page %d", i);
                            error = page[i]->SetHint(text);
                            if (error == SFERR_NO_ERROR) {

                                // 画像をリソースファイルから読み込む
                                image = shell->LoadResImage(TAB_RES_FILE, IDI_OBJECT_5001 + i);
                                if (image != null) {

                                    // タブページのタイトル画像を設定する ( リソースファイルやファイルから設定可能 )
                                    page[i]->SetImage(image);

                                    // タブページの状態を「可視+活性+操作可能+非フォーカス」にまとめて設定する
                                    // ※この状態はタブページのデフォルト初期設定と同じなので次の 1 行は無くても構わない
                                    page[i]->SetState(true, true, true, false);

                                    // タブページの中央にボタンを追加する

                                    // ボタンを作成する
                                    if ((button[i] = SFZTextButtonControl::NewInstance(&error)) != null) {

                                        // ボタンの親をタブページに設定する
                                        error = button[i]->SetParent(page[i]);

                                        if (error == SFERR_NO_ERROR) {

                                            // ボタンのラベルを設定する
                                            error = button[i]->SetText(SFXWideString::Format("Button %c", 'A' + i));

                                            if (error == SFERR_NO_ERROR) {

                                                // ボタンに最適な領域サイズを計算する
                                                rectangle = button[i]->GetSuitableBound(page[i]->GetLocalBound());

                                                // ボタンをタブページの中央に配置する
                                                rectangle.SnapCenterMiddle(page[i]->GetLocalBound().GetCenterMiddle());

                                                // ボタンの実領域を設定する
                                                button[i]->SetRealBound(rectangle);

                                                // ボタンの状態を「可視+活性+操作可能+フォーカス」にまとめて設定する
                                                button[i]->SetState(true, true, true, true);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    if (error != SFERR_NO_ERROR) break;
                }
                if (error == SFERR_NO_ERROR) {

                    // FocusPage 関数の引数にタブページのインデックスを指定して
                    // 1 ページ目のタブページを最前面に移動させる(表示させる)
                    _tab->FocusPage(0);

                    // ★★★  禁止事項  ★★★
                    // 選択されているタブが現在表示されているタブページに一致しなくなる可能性があるため、
                    // 下記の方法によりタブページを最前面に移動させようとしてはいけない

                    // 方法 1. 1 ページ目のタブページにフォーカスを移動することで最前面に移動させる
                    // × page[0]->SetStateFocus(true);

                    // 方法 2. ToFront 関数を呼び出して 1 ページ目のタブページを最前面に移動させる
                    // × page[0]->ToFront();

                    // ■□■  タブページの仮想領域設定  ■□■
                    // ※1. タブページの子レスポンダがタブコントロールのコンテント領域外に配置される場合は、
                    //      SFYTabControl::AdjustPages 関数を呼び出してタブページの仮想領域を設定する必要がある 
                    // ※2. この例では、タブページの子レスポンダの配置がすべてコンテント領域内に収まっているので、
                    //      SFYTabControl::AdjustPages 関数を呼び出す必要はない 
                }
            }
        }
    }

    return error;
}

コントロール値の役割と制限について

最小値は、常に 0 です。

現在値は、選択されているタブページのインデックスを表します。 タブページが存在しない場合は -1 になります。 タブページの選択は、 SFYControl::SetCurrentValue 関数ではなく SFYTabControl::FocusPage 関数を使用します。

最大値は、タブコントロールのタブページ数を表します(※この機能は将来的に廃止される予定です)。 タブページ数の取得には、SFYTabControl::GetPageCount 関数を使用してください。

フィールド値は、タブの数を表します。 必ず 1 以上の値を設定する必要があります。

トップ値は、一番左側のタブに対応するタブページのインデックスを表します。

仕様上の制限

タブコントロールの子レスポンダに、 SFZTabPage クラスかそれを継承するクラス以外のレスポンダを登録した時の動作は未定義です。

SFYControl::SetMinimumValue, SFYControl::SetMaximumValue, SFYControl::SetCurrentValue で最小値、最大値、現在値を変更してはいけません。

9.20.20. ソフトキーコントロール[SFZSoftKeyControl]

ソフトキーコントロール(SFZSoftKeyControl)は、 ソフトキーのキーイベントを処理するコントロールです。 このコントロールは、画面最下部にソフトキーメニューを表示し、ソフトキーのキーイベント[SFEVT_KEY]を受信すると、 現在表示されているソフトキーメニューに関連付けられているレスポンダにソフトキーイベント[SFEVT_RESPONDER_SOFTKEY]を送信します。

ソフトキーコントロールには、以下の 2 種類が存在します。 (標準スタイルがデフォルトです)

  1. 標準スタイル: ソフトキーメニューが 3 つのソフトキーラベルから構成される[デフォルト]
  2. 拡張スタイル: ソフトキーメニューが 5 つのソフトキーラベルと 4 つの上下左右キーラベルから構成される

図 9.75. 標準スタイル


標準スタイル

標準スタイル: ソフトキーメニューが 3 つのソフトキーラベルから構成される[デフォルト]

図 9.76. 拡張スタイル


拡張スタイル

拡張スタイル: ソフトキーメニューが 5 つのソフトキーラベルと 4 つの上下左右キーラベルから構成される

■ ソフトキーコントロールのレイアウト

標準スタイル:

拡張スタイル:

[Note] ソフトキーコントロールの背景色

ソフトキーコントロール(SFZSoftKeyControl)のデフォルトの背景色は、 SFXRGBColor(0xCC, 0xCC, 0xCC, 0x00) [灰色]です。

この背景色は、SFYWidget::SetBackgroundColor 関数を使用して変更可能です。

■ ソフトキーコントロールの機能

  1. 携帯電話の画面最下部に表示される複数のソフトキーメニューを管理します。
  2. ソフトキーメニューを構成する各種ラベル(セレクトキー、ソフトキー 1 〜 4、上下左右キーのラベル)に関する、 『テキスト、画像、3 色(※)』の要素を管理します。
  3. ソフトキーメニューとレスポンダの関連付け(バインド)を行います。
  4. 『アクティブレスポンダ(※)』にバインドされたソフトキーメニュー(『アクティブメニュー(※)』)を表示します。
  5. ソフトキー 1 〜 4 のキーイベント[SFEVT_KEY]を受信し、 『アクティブレスポンダ(※)』にソフトキーイベント[SFEVT_RESPONDER_SOFTKEY]を送信します。
[Note] テキスト、画像、3 色の要素

ソフトキーメニューを構成する各種ラベルに関する 『テキスト、画像、3 色』の要素は、 固有のキーで管理され、複数のラベル間で共有できます。

3 色とは、フレーム色、前景色、および背景色を表します。

[Note] アクティブレスポンダ

『アクティブレスポンダ』とは、 ソフトキーメニューにバインドされた、 フォーカス状態にあるレスポンダの中で、 最前面に配置されているレスポンダのことです。

[Note] アクティブメニュー

『アクティブメニュー』とは、 『アクティブレスポンダ』にバインドされたソフトキーメニューのことです。

■ SFZSoftKeyControl クラスの使い方

以下、window1 と window2 という 2 つのウィンドウを持つ application というアプリケーションクラスについて説明します。

  1. ソフトキーコントロールのインスタンスを生成します。

    // 1 アプリにつき 1 つのソフトキーコントロールを作成する
    _softkey = SFZSoftKeyControl::NewInstance(&error);
    
  2. ソフトキーコントロールの親レスポンダを application が内部で保持するルートに設定します。 このとき、ソフトキーコントロールはルートの子レスポンダの中で常に最前面になるように自動配置されます。

    // 親レスポンダはアプリケーションクラスが内部で保持するルートに設定する
    _softkey->SetParent(GetThis());
    
  3. ソフトキーコントロールのスタイルを標準スタイル[デフォルト]または拡張スタイルに設定します。

    // スタイルを拡張スタイルに設定する
    _softkey->SetStyle(SFZSoftKeyControl::EXTENSION);
    
  4. ソフトキーコントロールの実領域を SFYResponder::GetSuitableBound() の戻り値に設定します。

    // 実領域は SFYResponder::GetSuitableBound() の戻り値に設定する
    // ※ソフトキーコントロールのスタイルに応じて携帯電話の画面最下部に最適な実領域が自動計算される
    _softkey->SetRealBound(_softkey->GetSuitableBound());
    
    [Caution] 注意事項

    ソフトキーコントロールでは、 SFYResponder::GetSuitableBound 関数は、 引数に矩形領域が指定されても無視します。

    また、他のレスポンダの SFYResponder::GetSuitableBound 関数は最適なサイズだけを返しますが、 ソフトキーコントロールの場合、 最適なサイズの他に最適な始点も返します。 従って、実領域の始点を設定する必要はありません。

  5. ソフトキーコントロールの状態を「可視+活性+操作不能+非フォーカス」に設定します。

    // 状態を「可視+活性+操作不能+非フォーカス」に設定する
    _softkey->SetState(true, true, false, false);
    
  6. ラベルの要素(テキスト、画像、3 色)を登録します。

    [Note] 注意

    ラベルの要素(テキスト、画像、3 色)は、固有のキーで管理され、複数のラベル間で共有できます。

    // ラベルの要素(テキスト、画像、3 色)を登録する
    // ※3 色(フレーム色、前景色、背景色)は、同じキー "KEY_COLOR" で登録する
    _softkey->RegisterText(KEY_TEXT, text);                 // テキスト
    _softkey->RegisterImage(KEY_IMAGE, image);              // 画像
    _softkey->RegisterFrameColor(KEY_COLOR, colorFrame);    // フレーム色
    _softkey->RegisterForeColor(KEY_COLOR, colorFore);      // 前景色
    _softkey->RegisterBackColor(KEY_COLOR, colorBack);      // 背景色
    
  7. ソフトキーメニューを作成します。

    [Note] 注意

    ソフトキーメニューは、固有のキーで管理され、複数のレスポンダ間で共有できます。

    // ソフトキーメニューを作成する
    _softkey->CreateMenu(KEY_MENU);
    
  8. ソフトキーメニューのラベルについて、 要素(テキスト、画像、3 色)のキーを設定します。

    // ソフトキー 1 のラベルについて、テキスト、要素(テキスト、画像、3 色)のキーを設定する
    _softkey->SetTextKey(KEY_MENU, SFZSoftKeyControl::SOFTKEY_1, KEY_TEXT);
    _softkey->SetImageKey(KEY_MENU, SFZSoftKeyControl::SOFTKEY_1, KEY_IMAGE);
    _softkey->SetColorKey(KEY_MENU, SFZSoftKeyControl::SOFTKEY_1, KEY_COLOR);
    
  9. window1 のコンストラクタでは、以下の処理を行います。

    [Note] 注意

    SFZWindowSFZTextMenu などの SophiaFramework UNIVERSE 標準レスポンダの場合は、外部から同様の処理を行います。

    1. ソフトキーコントロールのインスタンスを取得します。

      // ソフトキーコントロールのインスタンスを取得する
      _softkey = USRApplication::GetSoftKey();
      
      [Note] 注意
      USRApplication::GetSoftKey() はソフトキーコントロールのインスタンスを取得するためのユーザー定義関数です。
    2. window1 をソフトキーコントロールのソフトキーメニューにバインドします。

      // ウィンドウをソフトキーコントロールのソフトキーメニューにバインドする
      _softkey->Bind(GetThis(), MENU_KEY);
      
    3. window1 にソフトキーイベント[SFEVT_RESPONDER_SOFTKEY]のハンドラを登録します。

      [Note] 注意
      ソフトキーイベントのハンドラ OnSoftkey の宣言と実装も必要です
      // ソフトキーイベントのハンドラを登録する
      RegisterHandler(
          SFXEventRange(SFEVT_RESPONDER_SOFTKEY, SFEVT_RESPONDER_SOFTKEY, AVK_SOFT1, AVK_SOFT4),
          XANDLER_INTERNAL(OnSoftkey)
      );
      // ※ソフトキーイベントのハンドラ OnSoftkey の宣言と実装も必要
      
    4. window1 のソフトキーメニューを表示する必要がなくなればアンバインドします。

      // ソフトキーコントロールからウィンドウをアンバインドする
      // バインドされたレスポンダが無効になれば自動的にアンバイドされるので省略可能
      _softkey->UnBind(GetThis());
      
  10. window2 も window1 と同様です。
[Note] ソフトキーコントロールの仕組み

ソフトキーコントロールでは、 1 つのソフトキーメニューを複数のレスポンダに関連付けることが可能です。

バインドされている何れかのレスポンダがフォーカス状態にあるとき、 ソフトキーコントロールは『アクティブ』であると呼びます。 そして、その中で最前面にあるレスポンダを『アクティブレスポンダ』と呼びます。

画面には、『アクティブレスポンダ』に関連付けられているソフトキーメニュー (『アクティブメニュー』と呼ぶ)が表示されます。

ソフトキーコントロールは、 ソフトキー 1 〜 4 のキーイベント[SFEVT_KEY]を受信し、 それをソフトキーイベント[SFEVT_RESPONDER_SOFTKEY]として 『アクティブレスポンダ』に送信します。

ソフトキーコントロールが『アクティブ』でない場合、 ソフトキーイベント[SFEVT_RESPONDER_SOFTKEY] はいずれのレスポンダにも送信されません。 このとき、画面にはメニューキー "0" で登録されている『デフォルトメニュー』が表示されます。

※ソフトキーコントロールは、セレクトキーや上下左右キーのキーイベントを処理しません。

[Note] デフォルトメニュー

デフォルトメニューとは、 ソフトキーコントロールが『アクティブ』でない、 つまり、『アクティブレスポンダ』が存在しない場合に表示されるデフォルトのソフトキーメニューのことです。

デフォルトメニューは、 ソフトキーコントロールのインスタンス生成時に自動的に作成され、メニューキー "0" で登録されています。

デフォルトメニューの初期値は、以下の通りです。

  1. 前景色: SFXRGBColor(0xFF, 0xFF, 0xFF, 0x00)[白色]
  2. 背景色: SFXRGBColor(0x77, 0x77, 0x77, 0x00)[灰色]
  3. フレーム色: SFXRGBColor(0xDD, 0xDD, 0xDD, 0xDD)[薄灰色]
  4. ラベルのテキスト: SFXWideString::EmptyInstance()
  5. ラベルの画像: SFBImageSmp::EmptyInstance()

※1. 上記の初期値は、 SFZSoftKeyControl::SetTextKey / SFZSoftKeyControl::SetImageKey / SFZSoftKeyControl::SetColorKey 関数を使用して、 メニューキー "0" の各ラベルに関する『テキスト、画像、3 色』の要素のキーを設定することにより変更できます。

※2. ラベルの有効状態は、デフォルト設定では有効("true")であるため、そのままではラベル領域は表示されます。 ラベル領域を非表示にするには、 SFZSoftKeyControl::SetEnable 関数を使用して有効状態を無効("false")に設定する必要があります。

[Caution] ソフトキーイベント

ソフトキーコントロールの親レスポンダをルートSFZRoot)に設定すると、 下記の配信規則がルートのトレーサに自動登録されます。

// ソフトキーコントロールの親レスポンダをルートに設定した際に
// ルートのトレーサに自動登録される配信規則
root->RegisterTracer(
                   SFXEventRange(SFEVT_KEY, SFEVT_KEY, AVK_SOFT1, AVK_SOFT4),
                   SFYTracer::ORDER_FORWARD, 
                   SFYTracer::STATE_ALL, 
                   false
);

この配信規則の意味は、以下の通りです。

  1. 状態に関係なく前面から背面へソフトキー 1 〜 4 のキーイベントを子レスポンダに配信する。
  2. あるレスポンダでイベントが処理されると、 そこでイベントの配信を終了する(重複処理はしない)。

ソフトキーコントロールはルート内で最前面に配置されるレスポンダなので、 ルートの次にソフトキー 1 〜 4 のキーイベントを受信します。

『アクティブ』であるソフトキーコントロールは、ソフトキー 1 〜 4 のキーイベントを受信し、 『アクティブレスポンダ』へソフトキーイベント[SFEVT_RESPONDER_SOFTKEY]を送信する処理を行います。

『アクティブ』でないソフトキーコントロールは、 ソフトキー 1 〜 4 のキーイベントを受信しますが、どのレスポンダにもソフトキーイベントを送信しない処理を行います("true" を返すだけの処理を行います)。

※『アクティブ』の如何を問わず、 ソフトキーコントロールはソフトキー 1 〜 4 のキーイベントを処理します。 従って、ルートを除き、他のレスポンダがソフトキー 1 〜 4 のキーイベントを受信することはありません。

例 9.126. アプリケーションクラスでのソフトキーコントロールの作成

// screensaver_sfy アプリケーションクラスの定義
SFMTYPEDEFCLASS(screensaver_sfy)
class screensaver_sfy: public SFYApplication {
    SFMSEALCOPY(screensaver_sfy)
private:
    SFZSoftKeyControlSmp _softkey;  // ソフトキーコントロールはアプリケーションクラスのメンバ変数として保持する
    MainWindowSmp _main;
public:
    static SFCInvokerPtr Factory(Void);
    static SFZSoftKeyControlSmp GetSoftKey(Void);
private:
    explicit screensaver_sfy(Void) static_throws;
    virtual ~screensaver_sfy(Void);
    XANDLER_DECLARE_VOIDRENDER(OnRenderRequest)
};

// screensaver_sfy アプリケーションクラスのコンストラクタ
screensaver_sfy::screensaver_sfy(Void) static_throws
{
    SFCError error;

    if (static_try()) {

        // ...(省略)...

        if (static_try()) {

           // ソフトキーコントロールを作成する
           // ※アプリケーションクラスはソフトキーコントロールを 1 つまで保持できる
           _softkey = SFZSoftKeyControl::NewInstance(&error);

           if (_softkey != null) {

                // ソフトキーコントロールの各種設定を行う

                // 親レスポンダをルートに設定する
                // ※1. ソフトキーコントロールの親レスポンダはルートでなければいけない
                // ※2. 内部処理によりソフトキーコントロールは常に最前面に配置される
                // ※3. ソフトキーコントロールはルートの次にソフトキー 1 〜 4 のキーイベントを受信する
                error = _softkey->SetParent(GetThis());


                if (error == SFERR_NO_ERROR) {

                    // スタイルを『拡張スタイル』に設定する
                    _softkey->SetStyle(SFZSoftKeyControl::EXTENSION);

                    // GetSuitableBound 関数を使用して実領域を設定する
                    // ★ソフトキーコントロール固有の GetSuitableBound() の仕様
                    // ※1. 引数には何も指定しない(指定しても無視される)
                    // ※2. 最適な始点の位置も自動計算される
                    _softkey->SetRealBound(_softkey->GetSuitableBound());

                    // 状態を「可視+活性+操作不能+非フォーカス」に設定する
                    _softkey->SetState(true, true, false, false);

                    // _softkey->ToFront();  // 自動的に実行されるので不要

                    // 要素(テキスト、画像、3 色)を登録する
                    // ※1. 要素はソフトキーメニューの使用前に登録する
                    // ※2. 登録しなかった画像と 3 色は、デフォルト設定となる
                    _softkey->RegisterText(IDS_SK_EXIT,   SFXWideString("終了"));
                    _softkey->RegisterText(IDS_SK_EDIT,   SFXWideString("設定"));
                    _softkey->RegisterText(IDS_SK_ADD,    SFXWideString("追加"));
                    _softkey->RegisterText(IDS_SK_CHANGE, SFXWideString("変更"));
                    _softkey->RegisterText(IDS_SK_REMOVE, SFXWideString("削除"));

                    // ※リソースファイルからの一括登録も可能
                    // _softkey->RegisterTextRange(
                    //   IDS_SK_EXIT, SFXPath(SCREENSAVER_SFY_RES_FILE), IDS_SK_EXIT, IDS_SK_REMOVE
                    // );
                }
            }
        }

        // MainWindow を作成する
        if (error == SFERR_NO_ERROR) {

            _main = MainWindow::NewInstance(&error);

            // ...(省略)...
        }

        // ...(省略)...
    }
}

// ソフトキーコントロールを取得する関数の実装
SFZSoftKeyControlSmp screensaver_sfy::GetSoftKey(Void)
{
    return static_cast<screensaver_sfyPtr>(GetInstance())->_softkey;
}

例 9.127. レスポンダクラスでのソフトキーコントロールの設定

// MainWindow の定義
SFMTYPEDEFRESPONDER(MainWindow)
class MainWindow: public SFZWindow {
    SFMSEALRESPONDER(MainWindow)
    SFMRESPONDERINSTANTIATEFOUR(MainWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
public:

    // ...(省略)...

private:
    SFZSoftKeyControlSmp _softkey;// ソフトキーコントロール

    // ...(省略)...

private:
    XANDLER_DECLARE_VOIDEVENT(OnKey)     // キーハンドラ
    XANDLER_DECLARE_VOIDEVENT(OnSoftkey) // ソフトキーハンドラ

    // ...(省略)...

};

// MainWindow のコンストラクタ
MainWindow::MainWindow(Void) static_throws
{
    static SFXEventRange::AtomRecConst range[] = {
        { SFEVT_APP_SUSPEND,       SFEVT_APP_SUSPEND,       SFP16_BEGIN,   SFP16_END },
        { SFEVT_APP_RESUME,        SFEVT_APP_RESUME,        SFP16_BEGIN,   SFP16_END },

        // 通常のキーイベント
        { SFEVT_KEY,               SFEVT_KEY,               SFP16_BEGIN,   SFP16_END },

        // ソフトキーコントロールが送信するソフトキーイベント[SFEVT_RESPONDER_SOFTKEY]
        // ソフトキーのキーイベントは、ソフトキーイベント[SFEVT_RESPONDER_SOFTKEY]に変換される
        { SFEVT_RESPONDER_SOFTKEY, SFEVT_RESPONDER_SOFTKEY, AVK_SOFT1,     AVK_SOFT4 }
    };
    SFYHandler::RuleRec rule[lengthof(range)];

    if (static_try()) {
        SetType(CODE_TYPE);

        rule[0].spp = XANDLER_FUNCTION(OnSuspend);
        rule[0].reference = this;
        rule[1].spp = XANDLER_FUNCTION(OnResume);
        rule[1].reference = this;

        // キーハンドラ
        rule[2].spp = XANDLER_FUNCTION(OnKey);
        rule[2].reference = this;

        // ソフトキーハンドラ
        rule[3].spp = XANDLER_FUNCTION(OnSoftkey);
        rule[3].reference = this;

        // ハンドラの登録
        static_throw(RegisterHandler(atomic_cast(range), rule, lengthof(range)));

        // ソフトキーコントロールのインスタンスを取得する
        if ((_softkey = screensaver_sfy::GetSoftKey()) != null) {

            if (!_softkey->ContainsMenuKey(MENUID_MAIN)) {
                // 固有のキー MENUID_MAIN に対応するソフトキーメニューが作成されていなければ、

                // ソフトキーメニューを作成する
                _softkey->CreateMenu(MENUID_MAIN);

                // ソフトキーメニューの各要素のキーを設定する
                // ※1. 要素はアプリケーションクラスのコンストラクタ内で登録済み
                // ※2. 左から SELECT, SOFTKEY_1, SOFTKEY_2, SOFTKEY_3, SOFTKEY_4 のラベルに対応する
                UInt32 keyText[] = {
                    IDS_SK_ADD, IDS_SK_EXIT, IDS_SK_EDIT, IDS_SK_CHANGE, IDS_SK_REMOVE
                };
                _softkey->SetTextKey(MENUID_MAIN, keyText, lengthof(keyText));
           }

           //  MainWindow にソフトキーメニューを関連付ける
           _softkey->Bind(this, MENUID_MAIN); 
           // "_softkey->Bind(GetThis(), MENUID_MAIN);" と記述しても良いが、パフォーマンスがやや悪くなる
        }
    }
}

例 9.128. ソフトキーイベントのハンドラの実装

// MainWindow のソフトキーイベントのハンドラの実装
// ※MainWindow は、アクティブレスポンダのときにしかソフトキーイベントを受信しない
XANDLER_IMPLEMENT_VOIDEVENT(MainWindow, OnSoftkey, invoker, event)
{

    // ...(省略)...

    switch (event.GetP16()) {

        case AVK_SOFT1:

            // 終了確認ダイアログの作成

            // ...(省略)...
            break;

        case AVK_SOFT2:

            // メニューの作成

            // ...(省略)...
            break;

         case AVK_SOFT3:

            // 変更処理

            // ...(省略)...
            break;

        case AVK_SOFT4:

            // 削除処理

            // ...(省略)...
            break;
    }

    return;
}

□実行結果

9.20.21. コントロールを表す抽象クラス[SFYControl]

コントロールは、コンテナ内に配置されるように設計されたレスポンダです。

SFYControl は、各種コントロールを実装するための起点(基底クラス)となります。

すべてのコントロールは SFYControl クラスを継承し、 最大値、最小値、現在値をプロパティとして保持しています。

[Caution] 注意

最大値、最小値、現在値が表す内容は、コントロールの種類により異なります。 必ずしも『最小値 ≦ 現在値 ≦ 最大値』ではないことに注意してください。

例えば、SFYTabControl では、 最小値は常に 0 であり、タブページが存在しない場合、現在値と最大値は -1 です。

SFYControl を継承するレスポンダでは、 SFYControl::SFYControl / SFYWidget::SFYWidget コンストラクタで登録されたハンドラの処理により、 下記のイベントを受信すると、対応する下記の仮想関数(ハンドラ)が最初に呼び出されます。 その後、開発者がレスポンダに登録したハンドラが呼び出されることになります。

[Note] 注意

ハンドラの詳細については、 SFYControl::SFYControl / SFYWidget::SFYWidget コンストラクタの解説を参照してください。

[Tip] Tip

ハンドラを登録する手間を省略できるので、 通常、これらのイベント処理は仮想関数をオーバーライドして記述します。

表 9.25. イベント、仮想関数(ハンドラ)とデフォルト動作

イベント 仮想関数(ハンドラ) デフォルトの動作 オーバーライド
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_REQUEST) イベント SFYWidget::HandleBoundRequest 推奨
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_OPTIMIZE) イベント SFYWidget::HandleBoundOptimize 推奨
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_REAL) イベント SFYControl::HandleBoundReal 仮想領域を実領域に一致させる※1 任意
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_VIRTUAL) イベント SFYWidget::HandleBoundVirtual 任意
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_GLOBAL) イベント SFYWidget::HandleBoundGlobal 非推奨[廃止予定]
(SFEVT_RESPONDER_RENDER, SFP16_RENDER_REQUEST) イベント SFYWidget::HandleRenderRequest 任意

※デフォルトの動作にある "−" は何も実装していないことを表す。

[Note] 注釈

※1.SFYResponder::SetVirtualBound(SFXRectangle(SFXGrid::ZeroInstance(), GetRealBound().GetSize())) を実行します。つまり、仮想領域を実領域に一致させます。

ユーザー定義コントロールを作成するときに最低限必要なコードを示します。

例 9.129. 宣言

SFMTYPEDEFRESPONDER(USRControl)
class USRControl: public SFYControl {
    SFMSEALRESPONDER(USRControl)
    SFMRESPONDERINSTANTIATETHREE(USRControl, SFYControl, SFYWidget, SFYResponder)
public:

    // レスポンダのタイプを定義する
    // 小文字と記号のみからなるタイプは予約されているので使えない
    enum CodeEnum {
        CODE_TYPE = four_char_code('U', 'C', 'N', 'T')
    };
    SFMTYPEDEFTYPE(CodeEnum)

public:
    static USRControlSmp NewInstance(SFCErrorPtr exception = null);
protected:
    explicit USRControl(Void) static_throws;
    virtual ~USRControl(Void);

    // 親クラスで定義されている仮想関数のうち、実装が推奨される仮想関数
    virtual Void HandleBoundRequest(SFXRectanglePtr rectangle) const;
    virtual Void HandleBoundOptimize(SFXRectanglePtr rectangle) const;
    virtual Void HandleBoundVirtual(Void);
    virtual Void HandleRenderRequest(SFXGraphicsPtr graphics) const;
};

例 9.130. 実装

USRControl::USRControl(Void) static_throws
{
    if (static_try()) {

        // レスポンダのタイプを設定する
        SetType(CODE_TYPE);

        // 初期化処理を記述する
    }
}

USRControl::~USRControl(Void)
{
    // 終了処理を記述する
}

USRControlSmp USRControl::NewInstance(SFCErrorPtr exception)
{
    return static_pointer_cast<USRControl>(Factory(::new USRControl, exception));
}

Void USRControl::HandleBoundRequest(SFXRectanglePtr rectangle) const
{
    // コントロールに最適な大きさを計算して rectangle パラメータに設定する
    // この関数内では、rectangle の原点は変更せず、rectangle のサイズだけを設定する(推奨)

    return;
}

Void USRControl::HandleBoundOptimize(SFXRectanglePtr rectangle) const
{
    // コントロールに最適な大きさを rectangle パラメータ内の大きさに
    // 収まるように計算し、rectangle パラメータに設定する
    // この関数内では、rectangle の原点は変更せず、rectangle のサイズだけを設定する(推奨)

    return;
}

Void USRControl::HandleBoundVirtual(Void)
{
    // 仮想領域が変更された場合に再計算が必要なものがあれば、ここに記述する

    return;
}

Void USRControl::HandleRenderRequest(SFXGraphicsPtr graphics) const
{
    // コントロールを描画する

    return;
}

9.20.22. ラベルコントロールを表す抽象クラス[SFYLabelControl]

SFYLabelControl は、 各種ラベルコントロールを実装するための起点(基底クラス)となります。

SFYLabelControl は、 フォーカス枠の描画機能と操作キーの管理を実装し、 いくつかの仮想関数のデフォルトの動作も実装します。

操作キーは、SFYLabelControl::SetOperateKey 関数を使用して設定します。 デフォルトでは、セレクトキーが操作キーとして割り当てられています。

SFYLabelControl を継承するレスポンダでは、 SFYLabelControl::SFYLabelControl / SFYControl::SFYControl / SFYWidget::SFYWidget コンストラクタで登録されたハンドラの処理により、 下記のイベントを受信すると、対応する下記の仮想関数(ハンドラ)が最初に呼び出されます。 その後、開発者がレスポンダに登録したハンドラが呼び出されることになります。

[Note] 注意

ハンドラの詳細については、 SFYLabelControl::SFYLabelControl / SFYControl::SFYControl / SFYWidget::SFYWidget コンストラクタの解説を参照してください。

[Tip] Tip

ハンドラを登録する手間を省略できるので、 通常、これらのイベント処理は仮想関数をオーバーライドして記述します。

表 9.26. イベント、仮想関数(ハンドラ)とデフォルト動作

イベント 仮想関数(ハンドラ) デフォルトの動作 オーバーライド
SFYLabelControl::SetOperateKey で設定された操作キーの SFEVT_KEY イベント SFYLabelControl::HandleOperateKey 結果イベントを送信する※1 任意
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_REQUEST) イベント SFYWidget::HandleBoundRequest 推奨
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_OPTIMIZE) イベント SFYWidget::HandleBoundOptimize 推奨
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_REAL) イベント SFYControl::HandleBoundReal 仮想領域を実領域に一致させる※2 任意
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_VIRTUAL) イベント SFYWidget::HandleBoundVirtual 任意
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_GLOBAL) イベント SFYWidget::HandleBoundGlobal 非推奨[廃止予定]
(SFEVT_RESPONDER_RENDER, SFP16_RENDER_REQUEST) イベント SFYWidget::HandleRenderRequest 任意

※デフォルトの動作にある "−" は何も実装していないことを表す。

[Note] 注釈

※1.SFYResponder::InvokeForward(SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_OK, GetCurrentValue()), false) を実行します。

※2.SFYResponder::SetVirtualBound(SFXRectangle(SFXGrid::ZeroInstance(), GetRealBound().GetSize())) を実行します。つまり、仮想領域を実領域に一致させます。

ユーザー定義ラベルコントロールを作成するときに最低限必要なコードを示します。

例 9.131. 宣言

SFMTYPEDEFRESPONDER(USRLabelControl)
class USRLabelControl: public SFYLabelControl {
    SFMSEALRESPONDER(USRLabelControl)
    SFMRESPONDERINSTANTIATEFOUR(USRLabelControl, SFYLabelControl, SFYControl, SFYWidget, SFYResponder)
public:

    // レスポンダのタイプを定義する
    // 小文字と記号のみからなるタイプは予約されているので使えない
    enum CodeEnum {
        CODE_TYPE = four_char_code('U', 'L', 'B', 'L')
    };
    SFMTYPEDEFTYPE(CodeEnum)

public:
    static USRLabelControlSmp NewInstance(SFCErrorPtr exception = null);
protected:
    explicit USRLabelControl(Void) static_throws;
    virtual ~USRLabelControl(Void);

    // 親クラスで定義されている仮想関数のうち、実装が推奨される仮想関数
    virtual Void HandleBoundRequest(SFXRectanglePtr rectangle) const;
    virtual Void HandleBoundOptimize(SFXRectanglePtr rectangle) const;
    virtual Void HandleBoundVirtual(Void);
    virtual Void HandleRenderRequest(SFXGraphicsPtr graphics) const;
};

例 9.132. 実装

USRLabelControl::USRLabelControl(Void) static_throws
{
    if (static_try()) {

        // レスポンダのタイプを設定する
        SetType(CODE_TYPE);

        // ラベルコントロールは背景を持たないので透過モードに設定する
        SetPropertyTransparent(true);

        // 初期化処理を記述する
    }
}

USRLabelControl::~USRLabelControl(Void)
{
    // 終了処理を記述する
}

USRLabelControlSmp USRLabelControl::NewInstance(SFCErrorPtr exception)
{
    return static_pointer_cast<USRLabelControl>(Factory(::new USRLabelControl, exception));
}

Void USRLabelControl::HandleBoundRequest(SFXRectanglePtr rectangle) const
{
    // SFYLabelControl::DrawFocus 関数を利用するので、フォーカス枠の大きさ分だけ縮小する
    rectangle->Deflate(GetFocusMargin());

    // フォーカス枠内部に最適な大きさを計算して rectangle パラメータに設定する
    // この関数内では、rectangle の原点は変更せず、rectangle のサイズだけを設定する(推奨)

    // SFYLabelControl::DrawFocus 関数を利用するので、フォーカス枠の大きさ分だけ拡大する
    rectangle->Inflate(GetFocusMargin());

    return;
}

Void USRLabelControl::HandleBoundOptimize(SFXRectanglePtr rectangle) const
{
    // SFYLabelControl::DrawFocus 関数を利用するので、フォーカス枠の大きさ分だけ縮小する
    rectangle->Deflate(GetFocusMargin());

    // フォーカス枠内部に最適な大きさを rectangle パラメータ内の大きさに
    // 収まるように計算し、rectangle パラメータに設定する
    // この関数内では、rectangle の原点は変更せず、rectangle のサイズだけを設定する(推奨)

    // SFYLabelControl::DrawFocus 関数を利用するので、フォーカス枠の大きさ分だけ拡大する
    rectangle->Inflate(GetFocusMargin());

    return;
}

Void USRLabelControl::HandleBoundVirtual(Void)
{
    // 仮想領域が変更された場合に再計算が必要なものがあれば、ここに記述する

    return;
}

Void USRLabelControl::HandleRenderRequest(SFXGraphicsPtr graphics) const
{
    // SFYLabelControl::DrawFocus 関数を使用してフォーカス枠を描画する
    DrawFocus(graphics, GetLocalBound());

    // フォーカス枠内部を描画する

    return;
}

9.20.23. ボックスコントロールを表す抽象クラス[SFYBoxControl]

SFYBoxControl は、 各種ボックスコントロールを実装するための起点(基底クラス)となります。

SFYBoxControl は、 ボックスの描画機能と操作キーの管理を実装し、 いくつかの仮想関数のデフォルトの動作も実装します。

操作キーは、 SFYBoxControl::SetOperateKey 関数を使用して設定します。 デフォルトでは、セレクトキーが操作キーとして割り当てられています。

SFYBoxControl を継承するレスポンダでは、 SFYBoxControl::SFYBoxControl / SFYControl::SFYControl / SFYWidget::SFYWidget コンストラクタで登録されたハンドラの処理により、 下記のイベントを受信すると、対応する下記の仮想関数(ハンドラ)が最初に呼び出されます。 その後、開発者がレスポンダに登録したハンドラが呼び出されることになります。

[Note] 注意

ハンドラの詳細については、 SFYBoxControl::SFYBoxControl / SFYControl::SFYControl / SFYWidget::SFYWidget コンストラクタの解説を参照してください。

[Tip] Tip

ハンドラを登録する手間を省略できるので、 通常、これらのイベント処理は仮想関数をオーバーライドして記述します。

表 9.27. イベント、仮想関数(ハンドラ)とデフォルト動作

イベント 仮想関数(ハンドラ) デフォルトの動作 オーバーライド
SFYBoxControl::SetOperateKey で設定された操作キーの SFEVT_KEY イベント SFYBoxControl::HandleOperateKey 結果イベントを送信する※1 任意
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_REQUEST) イベント SFYWidget::HandleBoundRequest 推奨
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_OPTIMIZE) イベント SFYWidget::HandleBoundOptimize 推奨
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_REAL) イベント SFYControl::HandleBoundReal 仮想領域を実領域に一致させる※2 任意
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_VIRTUAL) イベント SFYWidget::HandleBoundVirtual 任意
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_GLOBAL) イベント SFYWidget::HandleBoundGlobal 非推奨[廃止予定]
(SFEVT_RESPONDER_RENDER, SFP16_RENDER_REQUEST) イベント SFYWidget::HandleRenderRequest 任意

※デフォルトの動作にある "−" は何も実装していないことを表す。

[Note] 注釈

※1.SFYResponder::InvokeForward(SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_OK, GetCurrentValue()), false) を実行します。

※2.SFYResponder::SetVirtualBound(SFXRectangle(SFXGrid::ZeroInstance(), GetRealBound().GetSize())) を実行します。つまり、仮想領域を実領域に一致させます。

ユーザー定義ボックスコントロールを作成するときに最低限必要なコードを示します。

例 9.133. 宣言

SFMTYPEDEFRESPONDER(USRBoxControl)
class USRBoxControl: public SFYBoxControl {
    SFMSEALRESPONDER(USRBoxControl)
    SFMRESPONDERINSTANTIATEFOUR(USRBoxControl, SFYBoxControl, SFYControl, SFYWidget, SFYResponder)
public:

    // レスポンダのタイプを定義する
    // 小文字と記号のみからなるタイプは予約されているので使えない
    enum CodeEnum {
        CODE_TYPE = four_char_code('U', 'B', 'O', 'X')
    };
    SFMTYPEDEFTYPE(CodeEnum)

public:
    static USRBoxControlSmp NewInstance(SFCErrorPtr exception = null);
protected:
    explicit USRBoxControl(Void) static_throws;
    virtual ~USRBoxControl(Void);

    // 親クラスで定義されている仮想関数のうち、実装が推奨される仮想関数
    virtual Void HandleBoundRequest(SFXRectanglePtr rectangle) const;
    virtual Void HandleBoundOptimize(SFXRectanglePtr rectangle) const;
    virtual Void HandleBoundVirtual(Void);
    virtual Void HandleRenderRequest(SFXGraphicsPtr graphics) const;
};

例 9.134. 実装

USRBoxControl::USRBoxControl(Void) static_throws
{
    if (static_try()) {

        // レスポンダのタイプを設定する
        SetType(CODE_TYPE);

        // 初期化処理を記述する
    }
}

USRBoxControl::~USRBoxControl(Void)
{
    // 終了処理を記述する
}

USRBoxControlSmp USRBoxControl::NewInstance(SFCErrorPtr exception)
{
    return static_pointer_cast<USRBoxControl>(Factory(::new USRBoxControl, exception));
}

Void USRBoxControl::HandleBoundRequest(SFXRectanglePtr rectangle) const
{
    // SFYBoxControl::DrawBox 関数を利用するので、ボックスマージンの大きさ分だけ縮小する
    rectangle->Deflate(GetBoxMargin());

    // ボックス内部に最適な大きさを計算して rectangle パラメータに設定する
    // この関数内では、rectangle の原点は変更せず、rectangle のサイズだけを設定する(推奨)

    // SFYBoxControl::DrawBox 関数を利用するので、ボックスマージンの大きさ分だけ拡大する
    rectangle->Inflate(GetBoxMargin());

    return;
}

Void USRBoxControl::HandleBoundOptimize(SFXRectanglePtr rectangle) const
{
    // SFYBoxControl::DrawBox 関数を利用するので、ボックスマージンの大きさ分だけ縮小する
    rectangle->Deflate(GetBoxMargin());

    // ボックス内部に最適な大きさを rectangle パラメータ内の大きさに
    // 収まるように計算し、rectangle パラメータに設定する
    // この関数内では、rectangle の原点は変更せず、rectangle のサイズだけを設定する(推奨)

    // SFYBoxControl::DrawBox 関数を利用するので、ボックスマージンの大きさ分だけ拡大する
    rectangle->Inflate(GetBoxMargin());

    return;
}

Void USRBoxControl::HandleBoundVirtual(Void)
{
    // 仮想領域が変更された場合に再計算が必要なものがあれば、ここに記述する

    return;
}

Void USRBoxControl::HandleRenderRequest(SFXGraphicsPtr graphics) const
{
    // SFYBoxControl::DrawBox 関数を使用してボックスを描画する
    DrawBox(graphics, GetLocalBound());

    // ボックス内部を描画する

    return;
}

9.20.24. ボタンコントロールを表す抽象クラス[SFYButtonControl]

SFYButtonControl は、 各種ボタンコントロールを実装するための起点(基底クラス)となります。

SFYButtonControl は、 ボタンと影の描画機能と操作キーの管理を実装し、 いくつかの仮想関数のデフォルトの動作も実装します。

操作キーは、 SFYButtonControl::SetOperateKey 関数を使用して設定します。 デフォルトでは、セレクトキーが操作キーとして割り当てられています。

SFYButtonControl を継承するレスポンダでは、 SFYButtonControl::SFYButtonControl / SFYControl::SFYControl / SFYWidget::SFYWidget コンストラクタで登録されたハンドラの処理により、 下記のイベントを受信すると、対応する下記の仮想関数(ハンドラ)が最初に呼び出されます。 その後、開発者がレスポンダに登録したハンドラが呼び出されることになります。

[Note] 注意

ハンドラの詳細については、 SFYButtonControl::SFYButtonControl / SFYControl::SFYControl / SFYWidget::SFYWidget コンストラクタの解説を参照してください。

[Tip] Tip

ハンドラを登録する手間を省略できるので、 通常、これらのイベント処理は仮想関数をオーバーライドして記述します。

表 9.28. イベント、仮想関数(ハンドラ)とデフォルト動作

イベント 仮想関数(ハンドラ) デフォルトの動作 オーバーライド
SFYButtonControl::SetOperateKey で設定された操作キーの SFEVT_KEY イベント SFYButtonControl::HandleOperateKey 任意
SFYButtonControl::SetOperateKey で設定された操作キーの SFEVT_KEY_PRESS イベント SFYButtonControl::HandleOperateKeyPress 任意
SFYButtonControl::SetOperateKey で設定された操作キーの SFEVT_KEY_RELEASE イベント SFYButtonControl::HandleOperateKeyRelease 結果イベントを送信する※1 任意
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_REQUEST) イベント SFYWidget::HandleBoundRequest 推奨
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_OPTIMIZE) イベント SFYWidget::HandleBoundOptimize 推奨
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_REAL) イベント SFYControl::HandleBoundReal 仮想領域を実領域に一致させる※2 任意
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_VIRTUAL) イベント SFYWidget::HandleBoundVirtual 任意
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_GLOBAL) イベント SFYWidget::HandleBoundGlobal 非推奨[廃止予定]
(SFEVT_RESPONDER_RENDER, SFP16_RENDER_REQUEST) イベント SFYWidget::HandleRenderRequest 任意

※デフォルトの動作にある "−" は何も実装していないことを表す。

[Note] 注釈

※1.SFYResponder::InvokeForward(SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_OK, GetCurrentValue()), false) を実行します。

※2.SFYResponder::SetVirtualBound(SFXRectangle(SFXGrid::ZeroInstance(), GetRealBound().GetSize())) を実行します。つまり、仮想領域を実領域に一致させます。

ユーザー定義ボタンコントロールを作成するときに最低限必要なコードを示します。

例 9.135. 宣言

SFMTYPEDEFRESPONDER(USRButtonControl)
class USRButtonControl: public SFYButtonControl {
    SFMSEALRESPONDER(USRButtonControl)
    SFMRESPONDERINSTANTIATEFOUR(USRButtonControl, SFYButtonControl, SFYControl, SFYWidget, SFYResponder)
public:

    // レスポンダのタイプを定義する
    // 小文字と記号のみからなるタイプは予約されているので使えない
    enum CodeEnum {
        CODE_TYPE = four_char_code('U', 'B', 'T', 'N')
    };
    SFMTYPEDEFTYPE(CodeEnum)

public:
    static USRButtonControlSmp NewInstance(SFCErrorPtr exception = null);
protected:
    explicit USRButtonControl(Void) static_throws;
    virtual ~USRButtonControl(Void);

    // 親クラスで定義されている仮想関数のうち、実装が推奨される仮想関数
    virtual Void HandleBoundRequest(SFXRectanglePtr rectangle) const;
    virtual Void HandleBoundOptimize(SFXRectanglePtr rectangle) const;
    virtual Void HandleBoundVirtual(Void);
    virtual Void HandleRenderRequest(SFXGraphicsPtr graphics) const;
};

例 9.136. 実装

USRButtonControl::USRButtonControl(Void) static_throws
{
    if (static_try()) {

        // レスポンダのタイプを設定する
        SetType(CODE_TYPE);

        // 初期化処理を記述する
    }
}

USRButtonControl::~USRButtonControl(Void)
{
    // 終了処理を記述する
}

USRButtonControlSmp USRButtonControl::NewInstance(SFCErrorPtr exception)
{
    return static_pointer_cast<USRButtonControl>(Factory(::new USRButtonControl, exception));
}

Void USRButtonControl::HandleBoundRequest(SFXRectanglePtr rectangle) const
{
    // SFYButtonControl::DrawButton 関数と SFYButtonControl::DrawShadow 関数を利用するので、
    // ボタンと影の大きさ分だけ縮小する
    rectangle->Deflate(GetShadowMargin());
    rectangle->Deflate(GetButtonMargin());

    // ボタン内部に最適な大きさを計算して rectangle パラメータに設定する
    // この関数内では、rectangle の原点は変更せず、rectangle のサイズだけを設定する(推奨)

    // SFYButtonControl::DrawButton 関数と SFYButtonControl::DrawShadow 関数を利用するので、
    // ボタンと影の大きさ分だけ拡大する
    rectangle->Inflate(GetButtonMargin());
    rectangle->Inflate(GetShadowMargin());

    return;
}

Void USRButtonControl::HandleBoundOptimize(SFXRectanglePtr rectangle) const
{
    // SFYButtonControl::DrawButton 関数と SFYButtonControl::DrawShadow 関数を利用するので、
    // ボタンと影の大きさ分だけ縮小する
    rectangle->Deflate(GetShadowMargin());
    rectangle->Deflate(GetButtonMargin());

    // ボタン内部に最適な大きさを rectangle パラメータ内の大きさに
    // 収まるように計算し、rectangle パラメータに設定する
    // この関数内では、rectangle の原点は変更せず、rectangle のサイズだけを設定する(推奨)

    // SFYButtonControl::DrawButton 関数と SFYButtonControl::DrawShadow 関数を利用するので、
    // ボタンと影の大きさ分だけ拡大する
    rectangle->Inflate(GetButtonMargin());
    rectangle->Inflate(GetShadowMargin());

    return;
}

Void USRButtonControl::HandleBoundVirtual(Void)
{
    // 仮想領域が変更された場合に再計算が必要なものがあれば、ここに記述する

    return;
}

Void USRButtonControl::HandleRenderRequest(SFXGraphicsPtr graphics) const
{
    // SFYButtonControl::DrawButton 関数と SFYButtonControl::DrawShadow 関数)を利用して
    // ボタンと影を描画する
    DrawButton(graphics, DrawShadow(graphics, GetLocalBound()));

    // ボタン内部を描画する

    return;
}

9.20.25. チェックボックスコントロールを表す抽象クラス[SFYCheckboxControl]

SFYCheckboxControl は、各種チェックボックスコントロールを実装するための起点(基底クラス)となります。

SFYCheckboxControl は、 チェックボックスと影の描画機能とチェック状態の切り替えを実装し、 いくつかの仮想関数のデフォルトの動作も実装します。

操作キーは、 SFYButtonControl::SetOperateKey 関数を使用して設定します。 デフォルトでは、セレクトキーが操作キーとして割り当てられています。

SFYCheckboxControl を継承するレスポンダでは、 SFYCheckboxControl::SFYCheckboxControl / SFYButtonControl::SFYButtonControl / SFYControl::SFYControl / SFYWidget::SFYWidget コンストラクタで登録されたハンドラの処理により、 下記のイベントを受信すると、対応する下記の仮想関数(ハンドラ)が最初に呼び出されます。 その後、開発者がレスポンダに登録したハンドラが呼び出されることになります。

[Note] 注意

ハンドラの詳細については、 SFYCheckboxControl::SFYCheckboxControl / SFYButtonControl::SFYButtonControl / SFYControl::SFYControl / SFYWidget::SFYWidget コンストラクタの解説を参照してください。

[Tip] Tip

ハンドラを登録する手間を省略できるので、 通常、これらのイベント処理は仮想関数をオーバーライドして記述します。

表 9.29. イベント、仮想関数(ハンドラ)とデフォルト動作

イベント 仮想関数(ハンドラ) デフォルトの動作 オーバーライド
SFYButtonControl::SetOperateKey で設定された操作キーの SFEVT_KEY イベント SFYButtonControl::HandleOperateKey 任意
SFYButtonControl::SetOperateKey で設定された操作キーの SFEVT_KEY_PRESS イベント SFYButtonControl::HandleOperateKeyPress 任意
SFYButtonControl::SetOperateKey で設定された操作キーの SFEVT_KEY_RELEASE イベント SFYCheckboxControl::HandleOperateKeyRelease チェック状態切り替え結果イベントを送信する※1 任意
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_REQUEST) イベント SFYWidget::HandleBoundRequest 推奨
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_OPTIMIZE) イベント SFYWidget::HandleBoundOptimize 推奨
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_REAL) イベント SFYControl::HandleBoundReal 仮想領域を実領域に一致させる※2 任意
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_VIRTUAL) イベント SFYWidget::HandleBoundVirtual 任意
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_GLOBAL) イベント SFYWidget::HandleBoundGlobal 非推奨[廃止予定]
(SFEVT_RESPONDER_RENDER, SFP16_RENDER_REQUEST) イベント SFYWidget::HandleRenderRequest 任意

※デフォルトの動作にある "−" は何も実装していないことを表す。

[Note] 注釈

※1.チェック状態を切り替えた後、SFYResponder::InvokeForward(SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_OK, GetCurrentValue()), false) を実行します。

※2.SFYResponder::SetVirtualBound(SFXRectangle(SFXGrid::ZeroInstance(), GetRealBound().GetSize())) を実行します。つまり、仮想領域を実領域に一致させます。

ユーザー定義チェックボックスコントロールを作成するときに最低限必要なコードを示します。

例 9.137. 宣言

SFMTYPEDEFRESPONDER(USRCheckboxControl)
class USRCheckboxControl: public SFYCheckboxControl {
    SFMSEALRESPONDER(USRCheckboxControl)
    SFMRESPONDERINSTANTIATEFIVE(USRCheckboxControl, SFYCheckboxControl, SFYButtonControl, SFYControl, SFYWidget, SFYResponder)
public:

    // レスポンダのタイプを定義する
    // 小文字と記号のみからなるタイプは予約されているので使えない
    enum CodeEnum {
        CODE_TYPE = four_char_code('U', 'C', 'H', 'K')
    };
    SFMTYPEDEFTYPE(CodeEnum)

public:
    static USRCheckboxControlSmp NewInstance(SFCErrorPtr exception = null);
protected:
    explicit USRCheckboxControl(Void) static_throws;
    virtual ~USRCheckboxControl(Void);

    // 親クラスで定義されている仮想関数のうち、実装が推奨される仮想関数
    virtual Void HandleBoundRequest(SFXRectanglePtr rectangle) const;
    virtual Void HandleBoundOptimize(SFXRectanglePtr rectangle) const;
    virtual Void HandleBoundVirtual(Void);
    virtual Void HandleRenderRequest(SFXGraphicsPtr graphics) const;
};

例 9.138. 実装

USRCheckboxControl::USRCheckboxControl(Void) static_throws
{
    if (static_try()) {

        // レスポンダのタイプを設定する
        SetType(CODE_TYPE);

        // チェックボックスコントロールのラベル部分は背景を持たないので透過モードに設定する
        SetPropertyTransparent(true);

        // 初期化処理を記述する
    }
}

USRCheckboxControl::~USRCheckboxControl(Void)
{
    // 終了処理を記述する
}

USRCheckboxControlSmp USRCheckboxControl::NewInstance(SFCErrorPtr exception)
{
    return static_pointer_cast<USRCheckboxControl>(Factory(::new USRCheckboxControl, exception));
}

Void USRCheckboxControl::HandleBoundRequest(SFXRectanglePtr rectangle) const
{
    // チェックボックスコントロールに最適な大きさを計算して rectangle パラメータに設定する
    // この関数内では、rectangle の原点は変更せず、rectangle のサイズだけを設定する(推奨)

    return;
}

Void USRCheckboxControl::HandleBoundOptimize(SFXRectanglePtr rectangle) const
{
    // チェックボックスコントロールに最適な大きさを rectangle パラメータ内の大きさに
    // 収まるように計算し、rectangle パラメータに設定する
    // この関数内では、rectangle の原点は変更せず、rectangle のサイズだけを設定する(推奨)

    return;
}

Void USRCheckboxControl::HandleBoundVirtual(Void)
{
    // 仮想領域が変更された場合に再計算が必要なものがあれば、ここに記述する

    return;
}

Void USRCheckboxControl::HandleRenderRequest(SFXGraphicsPtr graphics) const
{
    SFXGrid grid;

    // SFYCheckboxControl::DrawButton**/DrawShadow**/ DrawCheckmark** 関数を使用して、
    // チェックボックスと影を描画する

    // _height 変数はチェックボックス部分の高さを表し、
    // _origin 変数はチェックボックス部分の原点を表すものとする
    // ※これらの変数は、ラベル部分に使用するフォントの高さより計算する

    if (_height >= 28) {

        grid.Set(DrawShadow28(graphics, _origin));
        DrawButton27(graphics, grid);
        grid.Add(3, 3);
        DrawCheckmark21(graphics, grid);
    }
    else if (_height >= 14) {

        grid.Set(DrawShadow14(graphics, _origin));
        DrawButton13(graphics, grid);
        grid.Add(2, 2);
        DrawCheckmark09(graphics, grid);
    }

    // チェックボックスコントロールのラベル部分を描画する

    return;
}

9.20.26. ラジオボタンコントロールを表す抽象クラス[SFYRadiobuttonControl]

SFYRadiobuttonControl は、 各種ラジオボタンコントロールを実装するための起点(基底クラス)となります。

SFYRadiobuttonControl は、 ラジオボタンと影の描画機能と排他的なチェック状態の切り替えを実装し、 いくつかの仮想関数のデフォルトの動作も実装します。

操作キーは、 SFYButtonControl::SetOperateKey 関数を使用して設定します。 デフォルトでは、セレクトキーが操作キーとして割り当てられています。

SFYRadiobuttonControl を継承するレスポンダでは、 SFYRadiobuttonControl::SFYRadiobuttonControl / SFYButtonControl::SFYButtonControl / SFYControl::SFYControl / SFYWidget::SFYWidget コンストラクタで登録されたハンドラの処理により、 下記のイベントを受信すると、対応する下記の仮想関数(ハンドラ)が最初に呼び出されます。 その後、開発者がレスポンダに登録したハンドラが呼び出されることになります。

[Note] 注意

ハンドラの詳細については、 SFYRadiobuttonControl::SFYRadiobuttonControl / SFYButtonControl::SFYButtonControl / SFYControl::SFYControl / SFYWidget::SFYWidget コンストラクタの解説を参照してください。

[Tip] Tip

ハンドラを登録する手間を省略できるので、 通常、これらのイベント処理は仮想関数をオーバーライドして記述します。

表 9.30. イベント、仮想関数(ハンドラ)とデフォルト動作

イベント 仮想関数(ハンドラ) デフォルトの動作 オーバーライド
SFYButtonControl::SetOperateKey で設定された操作キーの SFEVT_KEY イベント SFYButtonControl::HandleOperateKey 任意
SFYButtonControl::SetOperateKey で設定された操作キーの SFEVT_KEY_PRESS イベント SFYButtonControl::HandleOperateKeyPress 任意
SFYButtonControl::SetOperateKey で設定された操作キーの SFEVT_KEY_RELEASE イベント SFYRadiobuttonControl::HandleOperateKeyRelease 排他的なチェック状態切り替え結果イベントを送信する※1 任意
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_REQUEST) イベント SFYWidget::HandleBoundRequest 推奨
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_OPTIMIZE) イベント SFYWidget::HandleBoundOptimize 推奨
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_REAL) イベント SFYControl::HandleBoundReal 仮想領域を実領域に一致させる※2 任意
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_VIRTUAL) イベント SFYWidget::HandleBoundVirtual 任意
(SFEVT_RESPONDER_BOUND, SFP16_BOUND_GLOBAL) イベント SFYWidget::HandleBoundGlobal 非推奨[廃止予定]
(SFEVT_RESPONDER_RENDER, SFP16_RENDER_REQUEST) イベント SFYWidget::HandleRenderRequest 任意

※デフォルトの動作にある "−" は何も実装していないことを表す。

[Note] 注釈

※1.排他的にチェック状態を切り替えた後、SFYResponder::InvokeForward(SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_OK, GetCurrentValue()), false) を実行します。

※2.SFYResponder::SetVirtualBound(SFXRectangle(SFXGrid::ZeroInstance(), GetRealBound().GetSize())) を実行します。つまり、仮想領域を実領域に一致させます。

ユーザー定義ラジオボタンコントロールを作成するときに最低限必要なコードを示します。

例 9.139. 宣言

SFMTYPEDEFRESPONDER(USRRadiobuttonControl)
class USRRadiobuttonControl: public SFYRadiobuttonControl {
    SFMSEALRESPONDER(USRRadiobuttonControl)
    SFMRESPONDERINSTANTIATESIX(USRRadiobuttonControl, SFYRadiobuttonControl, SFYCheckboxControl, SFYButtonControl, SFYControl, SFYWidget, SFYResponder)
public:

    // レスポンダのタイプを定義する
    // 小文字と記号のみからなるタイプは予約されているので使えない
    enum CodeEnum {
        CODE_TYPE = four_char_code('U', 'R', 'D', 'O')
    };
    SFMTYPEDEFTYPE(CodeEnum)

public:
    static USRRadiobuttonControlSmp NewInstance(SFCErrorPtr exception = null);
protected:
    explicit USRRadiobuttonControl(Void) static_throws;
    virtual ~USRRadiobuttonControl(Void);

    // 親クラスで定義されている仮想関数のうち、実装が推奨される仮想関数
    virtual Void HandleBoundRequest(SFXRectanglePtr rectangle) const;
    virtual Void HandleBoundOptimize(SFXRectanglePtr rectangle) const;
    virtual Void HandleBoundVirtual(Void);
    virtual Void HandleRenderRequest(SFXGraphicsPtr graphics) const;
};

例 9.140. 実装

USRRadiobuttonControl::USRRadiobuttonControl(Void) static_throws
{
    if (static_try()) {

        // レスポンダのタイプを設定する
        SetType(CODE_TYPE);

        // ラジオボタンコントロールのラベル部分は背景を持たないので透過モードに設定する
        SetPropertyTransparent(true);

        // 初期化処理を記述する
    }
}

USRRadiobuttonControl::~USRRadiobuttonControl(Void)
{
    // 終了処理を記述する
}

USRRadiobuttonControlSmp USRRadiobuttonControl::NewInstance(SFCErrorPtr exception)
{
    return static_pointer_cast<USRRadiobuttonControl>(Factory(::new USRRadiobuttonControl, exception));
}

Void USRRadiobuttonControl::HandleBoundRequest(SFXRectanglePtr rectangle) const
{
    // ラジオボタンコントロールに最適な大きさを計算して rectangle パラメータに設定する
    // この関数内では、rectangle の原点は変更せず、rectangle のサイズだけを設定する(推奨)

    return;
}

Void USRRadiobuttonControl::HandleBoundOptimize(SFXRectanglePtr rectangle) const
{
    // ラジオボタンコントロールに最適な大きさを rectangle パラメータ内の大きさに
    // 収まるように計算し、rectangle パラメータに設定する
    // この関数内では、rectangle の原点は変更せず、rectangle のサイズだけを設定する(推奨)

    return;
}

Void USRRadiobuttonControl::HandleBoundVirtual(Void)
{
    // 仮想領域が変更された場合に再計算が必要なものがあれば、ここに記述する

    return;
}

Void USRRadiobuttonControl::HandleRenderRequest(SFXGraphicsPtr graphics) const
{
    SFXGrid grid;

    // SFYRadiobuttonControl::DrawButton**/DrawShadow**/DrawCheckmark** 関数を使用して
    // ラジオボタンと影を描画する

    // _height 変数はラジオボタン部分の高さを表し、
    // _origin 変数はラジオボタン部分の原点を表すものとする
    // ※これらの変数は、ラベル部分に使用するフォントの高さより計算する

    if (_height >= 28) {

        grid.Set(DrawShadow28(graphics, _origin));
        DrawButton27(graphics, grid);
        grid.Add(8, 8);
        DrawCheckmark11(graphics, grid);
    }
    else if (_height >= 14) {

        grid.Set(DrawShadow14(graphics, _origin));
        DrawButton13(graphics, grid);
        grid.Add(4, 4);
        DrawCheckmark05(graphics, grid);
    }

    // ラジオボタンコントロールのラベル部分を描画する

    return;
}