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

9.16. ダイアログ(応用編)

ここでは、ダイアログ領域に最適なサイズを取得する方法と、 一定時間経過後に自動的にダイアログを閉じる方法について解説します。

9.16.1. ダイアログに最適な大きさを取得する

SFZMessageDialogSFZQuestionDialog では、 引数の矩形を指定しない場合の SFYResponder::GetSuitableBound 関数の振る舞いが他のレスポンダと異なります。

この場合、この関数は複数行のテキストメッセージ用領域に最適なサイズを計算するためにヒント値が必要になります。

具体的には、 これらのレスポンダの SFYResponder::GetSuitableBound 関数を呼び出すときに引数(矩形領域)を指定しない場合は、 予め SFYResponder::SetRealBound 関数で設定する実領域の横幅がヒント値として利用されます。

実際にヒント値がどのように利用されているかは、 SFZMessageDialog::HandleBoundRequest または SFZQuestionDialog::HandleBoundRequest を参照してください。

SFYResponder::GetSuitableBound 関数で引数(矩形領域)を指定する場合、 ダイアログに最適な大きさを計算する前に実領域をヒント値として予め設定する必要はありません。

SFYResponder::GetSuitableBound 関数で引数(矩形領域)を指定する場合と指定しない場合の違いは、 領域計算するときに矩形領域の高さを制限するかしないかという点にあります。

図 9.43. 動作例

動作例

例 9.76. 宣言

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

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

例 9.77. 実装

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

    if ((_dialog = SFZMessageDialog::NewInstance(&error)) != null) {

        error = _dialog->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            error = _dialog->SetIconImage(SFXPath("resource.bar"), IMAGE_ID);
            if (error == SFERR_NO_ERROR) {

                error = _dialog->SetMessageText("hello world\n\n"
                                                "0          \n"
                                                " 1         \n"
                                                "  2        \n"
                                                "   3       \n"
                                                "    4      \n"
                                                "     5     \n"
                                                "      6    \n"
                                                "       7   \n"
                                                "        8  \n"
                                                "         9 \n"
                                                "          0");

                if (error == SFERR_NO_ERROR) {

                    error = _dialog->SetButtonText("OK");
                    if (error == SFERR_NO_ERROR) {

                        // ヒント値として実領域を設定する
                        _dialog->SetRealBound(GetLocalBound().Deflate(10, 10));

                        // 矩形を指定せずにダイアログの最適な領域のサイズを取得する
                        rectangle.Set(_dialog->GetSuitableBound());

                        // ダイアログの最適な領域を画面の中央に配置する
                        rectangle.SnapCenterMiddle(GetLocalBound().GetCenterMiddle());

                        // ダイアログの実領域を設定する
                        _dialog->SetRealBound(rectangle);

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

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

    return error;
}

9.16.2. ダイアログのタイマーを使用する

図 9.44. 動作例

動作例

ダイアログのタイマー機能を使えば、 指定した時間が経過したときに ESCAPE キーを押下したときと同等の処理を自動的に行うことができます。

[Note] 注意
デフォルトの設定では、指定時間経過後にダイアログが自動的に閉じます。

スタートした後、タイマーはいつでも取り消したり巻き戻せます。

例 9.78. 宣言

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

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

例 9.79. 実装

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

    if ((_dialog = SFZMessageDialog::NewInstance(&error)) != null) {

        error = _dialog->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            error = _dialog->SetIconImage(SFXPath("resource.bar"), IMAGE_ID);
            if (error == SFERR_NO_ERROR) {

                error = _dialog->SetMessageText("hello world");
                if (error == SFERR_NO_ERROR) {

                    error = _dialog->SetButtonText("OK");
                    if (error == SFERR_NO_ERROR) {

                        _dialog->SetRealBound(_dialog->GetSuitableBound(GetLocalBound().Deflate(10, 10), SFYResponder::HORIZONTAL_CENTER, SFYResponder::VERTICAL_MIDDLE));
                        _dialog->SetState(true, true, true, true);
                        _dialog->ToFront();

                        // 10 秒経過して操作キー、ESCAPE キー、またはボタンが押下されなかった場合、
                        // HandleEscapeKey() を起動し、画面を再描画するようにタイマーをスケジュールする
                        // ※デフォルトの実装: 10 秒経過して操作キー、ESCAPE キー、またはボタンが押下されなかった場合 ダイアログを閉じる
                        _dialog->ScheduleTimer(10000);
                    }
                }
            }
        }
    }

    return error;
}
[Note] ダイアログのタイマー処理

SFZDialog::ScheduleTimer 関数を利用することで、 指定した時間内に操作キー、ESCAPE キー、またはボタンが押下されないと、 ESCAPE キーのキーイベントを受信したときと同等の処理をタイマーにスケジュールできます。

具体的には、SFZDialog::ScheduleTimer 関数で指定した時間が経過しても操作キー、ESCAPE キー、またはボタンが押下されなかったとき、 SFZDialog::HandleEscapeKey 関数を呼び出し、画面を再描画します。

SFZDialog::HandleEscapeKey 関数内で結果イベント [SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_ESCAPE, 0)]が発生し、結果イベントを受信するハンドラが起動されます。

上の例の場合、 "_dialog->ScheduleTimer(10000);" を実行することにより、 10 秒経過しても操作キー、ESCAPE キー、またはボタンが押下されなかったとき、 結果イベント [SFXEvent(SFEVT_RESPONDER_RESULT, SFP16_RESULT_ESCAPE, 0)] が発生します。

ここでは、結果イベントを受信するハンドラを登録していないので、デフォルトのハンドラが起動されます。 デフォルトのハンドラはダイアログを閉じるだけの処理を行います。