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

9.14. フレーム

フレームはウィンドウやダイアログなどのレスポンダに枠やタイトルなどの枠組みを設定する機能を提供します。

枠の種類には、影だけの枠、影付きの平面的な枠、影付きの立体的な枠の3種類があり、 それぞれプレーンフレーム、フラットフレーム、ベベルフレームと呼びます。フレームのヘッダー部分にタイトルを付けることも可能です。

図 9.39. 動作例 (各種フレーム)


各種フレーム

上段(左から) : プレーンフレーム[SFZPlainFrame]、 フラットフレーム[SFZFlatFrame]、 ベベルフレーム[SFZBevelFrame]

下段(左から) : タイトル付きプレーンフレーム[SFZTitlePlainFrame]、 タイトル付きフラットフレーム[SFZTitleFlatFrame]、 タイトル付きベベルフレーム[SFZTitleBevelFrame]

■フレームクラスを使うときの注意事項

  1. フレームは設定するウィンドウやダイアログなどのレスポンダの親レスポンダにします。
  2. フレームの領域から枠やタイトルなど枠組みの除く部分にコンテンツとなるウィンドウやダイアログなどのレスポンダを配置します。
  3. フレームを設定したウィンドウやダイアログを最前面に移動させるには、フレーム自身を最前面に移動するようにします。 ウィンドウやダイアログも自動的に最前面に配置されます。 ウィンドウやダイアログだけを最前面に移動させてフレームを最前面に移動しなかった場合、 枠組み部分が他のレスポンダに隠れて描画されなくなる可能性があります。
  4. 同じフレームを複数のウィンドウやダイアログが共有している場合は、 最前面に表示したいウィンドウやダイアログも最前面に移動させるようにします。
  5. フレームはアプリケーションクラス(ルート)の子クラスとして配置します。
  6. 開発者がフレームクラスを作成するときは、アプリケーション的なプロパティを持たせないことを推奨します。 そうすることにより、アプリケーションロジックを変更することなく別の種類のフレームに着せ替えることが可能になります。

すべてのフレームは SFYFrame クラスを継承し、 枠組み(余白)部分のサイズを計算したり、 枠やタイトルなどの枠組みを設定し描画する機能を提供します。

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

表 9.17. 具象フレームの種類

クラス名 解説
SFZPlainFrame プレーンフレームです。
SFZFlatFrame フラットフレームです。
SFZBevelFrame ベベルフレームです。
SFZTitlePlainFrame タイトル付きプレーンフレームです。
SFZTitleFlatFrame タイトル付きフラットフレームです。
SFZTitleBevelFrame タイトル付きベベルフレームです。

表 9.18. 抽象フレームの種類

クラス名 解説
SFYFrame フレームの抽象クラスです。
SFYPlainFrame プレーンフレームの抽象クラスです。
SFYFlatFrame フラットフレームの抽象クラスです。
SFYBevelFrame ベベルフレームの抽象クラスです。
[Important] 重要

すべてのフレームにおいて、 SFYResponder::SetParent 関数、 SFYResponder::SetState 関数、 SFYResponder::SetRealBound 関数の呼び出しは必須です。

また、フレームを設定したウィンドウやダイアログを最前面に移動させるには、 必ずフレームの SFYResponder::ToFront 関数を呼び出さなければいけません。

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

例 9.68. 宣言

SFMTYPEDEFCLASS(USRApplication)
class USRApplication : public SFYApplication {
    SFMSEALCOPY(USRApplication)
private:

    SFZTitleBevelFrameSmp _frame;
    SFZMessageDialogSmp _dialog;

    //  ...

private:
    SFCError MakeFrame(Void);
    SFCError MakeDialog(Void);


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

例 9.69. 実装

// フレームの作成
SFCError USRApplication::MakeFrame(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // タイトル付きベベルフレームの生成(フレームの種類によってデザインが異なる)
    // 他のフレームについても同様にしてウィンドウやダイアログに枠組みを設定できる
    if ((_frame = SFZTitleBevelFrame::NewInstance(&error)) != null) {

        // ※注意1:フレームの親をルートに設定する
        error = _frame->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

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

            // その他フレームの設定
            //  ...
        }
    }
    if ( error == SFERR_NO_ERROR) {

        // フレーム付きダイアログを作成し表示する
        error = MakeDialog();
    }

    return error;
}

// フレーム付きダイアログの作成と表示
SFCError USRApplication::MakeDialog(Void)
{
    SFXRectangle rectangle;
    SFXMargin margin;
    SFCError error(SFERR_NO_ERROR);

    // ダイアログの生成
    if ((_dialog = SFZMessageDialog::NewInstance(&error)) != null) {

        // ※注意2:ダイアログの親レスポンダをフレームにする
        error = _dialog->SetParent(_frame);
        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) {

                // メッセージ部分に表示するテキストを設定する
                error = _dialog->SetMessageText("in\nSFZTitleBevelFrame\n\nThis is a notification message.");
                if (error == SFERR_NO_ERROR) {

                    // OK ボタン部分に表示するテキストを設定する
                    error = _dialog->SetButtonText("OK");

                    if (error == SFERR_NO_ERROR) {

                        // フレームのタイトルを設定する
                        error = _frame->SetText("SFZTitleBevelFrame");

                        if (error == SFERR_NO_ERROR) {

                            // ダイアログに合ったフレームのサイズを計算する

                            // フレームの余白(影、枠、ベベル枠、ヘッダー)を取得する
                            margin.Set(_frame->GetSuitableMargin());

                            // ダイアログの最適な領域のサイズを計算する
                            rectangle.Set(_dialog->GetSuitableBound(GetLocalBound().Deflate(10, 10).Deflate(margin)));

                            // ダイアログにフレームの余白を付けてフレームの実領域のサイズを計算する
                            rectangle.Inflate(margin);

                            // フレームの実領域を画面中央に設定する
                            rectangle.SnapCenterMiddle(GetLocalBound().GetCenterMiddle());
                            _frame->SetRealBound(rectangle);

                            // ダイアログをフレームの中に配置する
                            _dialog->SetRealBound(_frame->GetLocalBound().Deflate(margin));

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

                            // ダイアログを最前面に移動する

                            // ※注意3:ダイアログの親であるフレームを最前面に移動する
                            _frame->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;
    }

    // フレームは親レスポンダなので、フレームを閉じるとダイアログも自動的に閉じる
    _frame->Terminate();

    return;
}
[Note] フレームの親レスポンダ

多くの場合、フレームの親レスポンダはアプリケーションクラス(ルート[SFZRoot])に設定します。

[Note] フレームとウィンドウやダイアログの親子関係

通常、フレームは枠組みを設定するウィンドウやダイアログの親レスポンダとなります。

[Note] 最前面への移動

フレームを設定したウィンドウやダイアログは、 親レスポンダであるフレームを最前面に移動することでフレームと共に自動的に最前面に移動します。

フレームの SFYResponder::ToFront 関数の呼び出しは必須です。 ウィンドウやダイアログだけを最前面に移動した場合、 フレームが他のレスポンダに隠れて表示されない可能性があります。

複数のウィンドウやダイアログが同じフレームを共有している場合、 最前面に移動させたいウィンドウまたはダイアログの SFYResponder::ToFront 関数も呼び出します。

[Note] フレーム付きのウィンドウやダイアログの閉じ方

ウィンドウやダイアログだけを閉じても親レスポンダであるフレームが残ってしまうので、 フレームを不可視状態にするか、 親レスポンダであるフレームを閉じることでウィンドウやダイアログをも自動的に閉じるようにします。