前のページ次のページ上に戻るホーム BREW C++ ライブラリ & GUI フレームワーク & XML ミドルウェア : SophiaFramework UNIVERSE 5.0

9.12. ダイアログ(基礎編)

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

すべてのダイアログは SFZDialog クラスを継承し、実領域よりも大きく設定された仮想領域のスクロール機能とフォーカスの移動機能に加え、一定時間経過後に自動的にダイアログを閉じる機能とデフォルトのキー操作機能を提供します。

ウィンドウと同様にコントロールを配置するためのコンテナとして利用できますが、ダイアログは一時的な画面を表示しユーザーに結果を選択させる目的で使用します。

具象ダイアログはアプレット開発ですぐに使うことができる部品であり、抽象ダイアログはカスタマイズされたユーザー定義ダイアログを作成するための起点となります。

表 9.14. 具象ダイアログの種類

クラス名 解説
SFZDialog コントロールやコンテナなどを配置する汎用ダイアログです。
SFZMessageDialog 通知メッセージを表示するダイアログです。
SFZQuestionDialog 選択メッセージを表示するダイアログです。

表 9.15. 抽象ダイアログの種類

クラス名 解説
SFZDialog ダイアログを表す抽象クラスです。
[Important] 重要

すべてのダイアログにおいて、SFYResponder::SetParent 関数、SFYResponder::SetState 関数、SFYResponder::SetRealBound 関数の呼び出しは必須です。

その他の関数は必要に応じて呼び出します。省略することも可能です。

9.12.1. コントロールやコンテナなどを配置する汎用ダイアログ [SFZDialog]

図 9.34. 動作例

動作例

SFZDialog クラスは、 各種コントロールやコンテナを配置するための汎用的なダイアログとして機能します。

コントロールやコンテナが配置されている場合、上下キーでフォーカスの移動機能を利用できます。

仮想領域が実領域よりも大きく設定されている場合、フォーカスの移動機能と連動した、仮想領域の上下方向へのスクロール機能を利用できます。

無操作状態で一定時間経過後に、自動的にダイアログを閉じたりイベントを受信したりできます。

セレクトキー押下時とクリアキー押下時にそれぞれに対応するイベントを受信できます。

例 9.56. 宣言

SFMTYPEDEFCLASS(USRApplication)
class USRApplication : public SFYApplication {
    SFMSEALCOPY(USRApplication)
private:
    SFZDialogSmp _dialog;

    ...
private:
    SFCError Make(Void);

    // ダイアログ選択結果イベントのハンドラ
    XANDLER_DECLARE_VOIDRESULT(OnResult)
};

例 9.57. 実装

SFCError USRApplication::Make(Void)
{
    SFXRectangle rectangle;
    SFCError error(SFERR_NO_ERROR);

    // ダイアログを作成する
    if ((_dialog = SFZDialog::NewInstance(&error)) != null) {

        // ダイアログの親レスポンダを USRApplication に設定する
        error = _dialog->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // ダイアログ選択結果イベントを処理するハンドラを登録する
            error = _dialog->RegisterHandler(
                SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END),
                XANDLER_INTERNAL(OnResult)
            );
            if (error == SFERR_NO_ERROR) {

                // ダイアログの最適な領域のサイズを計算する
                rectangle.Set(_dialog->GetSuitableBound(GetLocalBound().Deflate(10, 10)));
                // ダイアログの最適な領域を画面中央に配置する
                rectangle.SnapCenterMiddle(GetLocalBound().GetCenterMiddle());
                // ダイアログの実領域を設定する
                _dialog->SetRealBound(rectangle);

                // ダイアログの状態を「可視+活性+操作可能+フォーカス」にまとめて設定する
                _dialog->SetState(true, true, true, true);

                // ダイアログを最前面に移動する
                _dialog->ToFront();
            }
        }
    }
    return error;
}

// ダイアログ選択結果イベントを処理するハンドラ
XANDLER_IMPLEMENT_VOIDRESULT(USRApplication, OnResult, invoker, reason, result)
{
    switch (reason) {
        case SFP16_RESULT_OK:

            // セレクトキー押下時に受信され、result は常に 0 となる
            break;
        case SFP16_RESULT_ESCAPE:

            // 一定時間経過後に自動的にダイアログが閉じられる場合、またはクリアキー押下時、result は常に 0 となる
            break;
    }

    // ダイアログを閉じる
    _dialog->Terminate();
    return;
}

9.12.2. 通知メッセージを表示するダイアログ [SFZMessageDialog]

図 9.35. 動作例

動作例

SFZMessageDialog クラスは、 アイコンイメージ・メッセージテキスト・OK ボタンを表示できます。

それぞれの要素は省略することも可能です。

OK ボタンを省略、または操作不可能状態に設定する場合、セレクトキーでの操作が可能になります。

例 9.58. 宣言

SFMTYPEDEFCLASS(USRApplication)
class USRApplication : public SFYApplication {
    SFMSEALCOPY(USRApplication)
private:
    SFZMessageDialogSmp _dialog;

    ...
private:
    SFCError Make(Void);

    // ダイアログ選択結果イベントのハンドラ
    XANDLER_DECLARE_VOIDRESULT(OnResult)
};

例 9.59. 実装

SFCError USRApplication::Make(Void)
{
    SFXRectangle rectangle;
    SFCError error(SFERR_NO_ERROR);

    // ダイアログを作成する
    if ((_dialog = SFZMessageDialog::NewInstance(&error)) != null) {

        // ダイアログの親レスポンダを USRApplication に設定する
        error = _dialog->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // ダイアログ選択結果イベントを処理するハンドラを登録する
            error = _dialog->RegisterHandler(
                SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END),
                XANDLER_INTERNAL(OnResult)
            );
            if (error == SFERR_NO_ERROR) {

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

                    // メッセージ部分に表示するテキストを設定する
                    // SFXWideString オブジェクトの設定 (※リソースファイルから設定可能 )
                    error = _dialog->SetMessageText("hello world\n\nThis is a notification message.");
                    if (error == SFERR_NO_ERROR) {

                        // OK ボタン部分に表示するテキストを設定する
                        // SFXWideString オブジェクトの設定 (※リソースファイルから設定可能 )
                        error = _dialog->SetButtonText("OK");
                        if (error == SFERR_NO_ERROR) {

                            // ダイアログの最適な領域のサイズを計算する
                            rectangle.Set(_dialog->GetSuitableBound(GetLocalBound().Deflate(10, 10)));
                            // ダイアログの最適な領域を画面中央に配置する
                            rectangle.SnapCenterMiddle(GetLocalBound().GetCenterMiddle());
                            // ダイアログの実領域を設定する
                            _dialog->SetRealBound(rectangle);

                            // ダイアログの状態を「可視+活性+操作可能+フォーカス」にまとめて設定する
                            _dialog->SetState(true, true, true, true);

                            // ダイアログを最前面に移動する
                            _dialog->ToFront();
                        }
                    }
                }
            }
        }
    }
    return error;
}

// ダイアログ選択結果イベントを処理するハンドラ
XANDLER_IMPLEMENT_VOIDRESULT(USRApplication, OnResult, invoker, reason, result)
{
    switch (reason) {
        case SFP16_RESULT_OK:

            // OK ボタン押下時、またはセレクトキー押下時に受信され、result は常に 0 となる
            break;
        case SFP16_RESULT_ESCAPE:

            // 一定時間経過後に自動的にダイアログが閉じられる場合、またはクリアキー押下時、result は常に 0 となる
            break;
    }

    // ダイアログを閉じる
    _dialog->Terminate();
    return;
}

9.12.3. 選択メッセージを表示するダイアログ [SFZQuestionDialog]

図 9.36. 動作例

動作例

SFZQuestionDialog クラスは、 アイコンイメージ・メッセージテキスト・その他ボタン・OK ボタン・キャンセル ボタンを表示できます。

それぞれの要素は省略することも可能です。

すべてのボタンを省略、または操作不可能状態に設定する場合、セレクトキーでの操作が可能になります。

各種ボタンにテキストを設定する場合、最後に設定したボタンが始めにフォーカスされた状態で表示されます。

例 9.60. 宣言

SFMTYPEDEFCLASS(USRApplication)
class USRApplication : public SFYApplication {
    SFMSEALCOPY(USRApplication)
private:
    SFZQuestionDialogSmp _dialog;

    ...
private:
    SFCError Make(Void);

    // ダイアログ選択結果イベントのハンドラ
    XANDLER_DECLARE_VOIDRESULT(OnResult)
};

例 9.61. 実装

SFCError USRApplication::Make(Void)
{
    SFXRectangle rectangle;
    SFCError error(SFERR_NO_ERROR);

    // ダイアログを作成する
    if ((_dialog = SFZQuestionDialog::NewInstance(&error)) != null) {

        // ダイアログの親レスポンダを USRApplication に設定する
        error = _dialog->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // ダイアログ選択結果イベントを処理するハンドラを登録する
            error = _dialog->RegisterHandler(
                SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END),
                XANDLER_INTERNAL(OnResult)
            );
            if (error == SFERR_NO_ERROR) {

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

                    // メッセージ部分に表示するテキストを設定する
                    // SFXWideString オブジェクトの設定 (※リソースファイルから設定可能 )
                    error = _dialog->SetMessageText("hello world\n\nThis is a question message.");
                    if (error == SFERR_NO_ERROR) {

                        // その他ボタン部分に表示するテキストを設定する
                        // SFXWideString オブジェクトの設定 (※リソースファイルから設定可能 )
                        error = _dialog->SetButtonText(SFZQuestionDialog::BUTTON_ANOTHER, "ANOTHER");
                        if (error == SFERR_NO_ERROR) {

                            // キャンセル ボタン部分に表示するテキストを設定する
                            // SFXWideString オブジェクトの設定 (※リソースファイルから設定可能 )
                            error = _dialog->SetButtonText(SFZQuestionDialog::BUTTON_CANCEL, "CANCEL");
                            if (error == SFERR_NO_ERROR) {

                                // OK ボタン部分に表示するテキストを設定する
                                // SFXWideString オブジェクトの設定 (※リソースファイルから設定可能 )
                                error = _dialog->SetButtonText(SFZQuestionDialog::BUTTON_OK, "OK");
                                if (error == SFERR_NO_ERROR) {

                                    // ダイアログの最適な領域のサイズを計算する
                                    rectangle.Set(_dialog->GetSuitableBound(GetLocalBound().Deflate(10, 10)));
                                    // ダイアログの最適な領域を画面中央に配置する
                                    rectangle.SnapCenterMiddle(GetLocalBound().GetCenterMiddle());
                                    // ダイアログの実領域を設定する
                                    _dialog->SetRealBound(rectangle);

                                    // ダイアログの状態を「可視+活性+操作可能+フォーカス」にまとめて設定する
                                    _dialog->SetState(true, true, true, true);

                                    // ダイアログを最前面に移動する
                                    _dialog->ToFront();
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return error;
}

// ダイアログ選択結果イベントを処理するハンドラ
XANDLER_IMPLEMENT_VOIDRESULT(USRApplication, OnResult, invoker, reason, result)
{
    switch (reason) {
        case SFP16_RESULT_OK:

            // OK ボタン押下時、またはセレクトキー押下時に受信され、result は常に 0 となる
            break;
        case SFP16_RESULT_CANCEL:

            // キャンセル ボタン押下時に受信され、result は常に 0 となる
            break;
        case SFP16_RESULT_ANOTHER:

            // その他ボタン押下時に受信され、result は常に 0 となる
            break;
        case SFP16_RESULT_ESCAPE:

            // 一定時間経過後に自動的にダイアログが閉じられる場合、またはクリアキー押下時、result は常に 0 となる
            break;
    }

    // ダイアログを閉じる
    _dialog->Terminate();
    return;
}

9.12.4. ダイアログを表す抽象クラスとしての汎用ダイアログ [SFZDialog]

各種ダイアログを実装するための起点となります。

このクラスは、一定時間経過後に自動的にダイアログを閉じる機能と操作キーの管理を実装し、いくつかの仮想関数のデフォルトの動作も実装します。

複雑な機能を持ったダイアログを作成する場合、汎用ダイアログを継承して利用する方が開発が容易になることがあります。

表 9.16. 仮想関数名とデフォルトの動作

仮想関数名 デフォルトの動作 オーバーライド
SFZDialog::HandleOperateKey 結果イベントを送信※1 任意
SFZDialog::HandleEscapeKey 結果イベントを送信※2 任意
SFYContainer::HandleScrollUpKey 仮想領域を上方向にスクロール※3 任意
SFYContainer::HandleScrollDownKey 仮想領域を下方向にスクロール※4 任意
SFYContainer::HandlePageUpKey 仮想領域を上方向に1ページ分スクロール※5 任意
SFYContainer::HandlePageDownKey 仮想領域を下方向に1ページ分スクロール※6 任意
SFYContainer::HandleSnapUpKey 仮想領域を上端までスクロール※7 任意
SFYContainer::HandleSnapDownKey 仮想領域を下端までスクロール※8 任意
SFYWidget::HandleBoundRequest 推奨
SFYWidget::HandleBoundOptimize 推奨
SFYWidget::HandleBoundReal 任意
SFYWidget::HandleBoundVirtual 任意
SFYWidget::HandleBoundGlobal 任意
SFYWidget::HandleRenderRequest 任意
[Note] 注釈

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

※2.InvokeForward(SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_ESCAPE, 0), false) を実行します。

※3.ScrollUp() を実行します。

※4.ScrollDown() を実行します。

※5.PageUp() を実行します。

※6.PageDown() を実行します。

※7.SnapUp() を実行します。

※8.SnapDown() を実行します。

以下にユーザー定義ダイアログを作成するときに最低限必要なコードを示します。

例 9.62. 宣言

SFMTYPEDEFRESPONDER(USRDialog)
class USRDialog : public SFZDialog {
    SFMSEALRESPONDER(USRDialog)
    SFMRESPONDERINSTANTIATEFIVE(USRDialog, SFZDialog, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
public:

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

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

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

例 9.63. 実装

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

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

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

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

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

Void USRDialog::HandleBoundRequest(SFXRectanglePtr rectangle) const
{
    // ダイアログに最適な大きさを計算して rectangle パラメータに設定する
    // 原点は変更せず、サイズだけを設定することを推奨

    return;
}

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

    return;
}

Void USRDialog::HandleBoundReal(Void)
{
    // 実領域が変更された場合に再計算が必要なものがあれば、ここに記述する
    return;
}

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

Void USRDialog::HandleRenderRequest(SFXGraphicsPtr graphics) const
{
    // ダイアログを描画する
    return;
}