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

3.10. フレーム

フレームは、 ウィンドウやダイアログ、メニューなどのレスポンダに枠やタイトルを装着する機能を提供します。

フレームを装着するには、 引数にフレームを指定して装着対象レスポンダの SFYResponder::SetFrame 関数を呼び出します。

3.10.1. タイトル付きフレーム(プレーンフレームとベベルフレーム)

下図のタイトル付きプレーンフレーム(SFZTitlePlainFrame)/タイトル付きベベルフレーム(SFZTitleBevelFrame) を装着したウィンドウとダイアログを作成します

図 3.45. タイトル付きプレーンフレームを装着したウィンドウ

タイトル付きプレーンフレームを装着したウィンドウ

図 3.46. タイトル付きベベルフレームを装着したダイアログ

タイトル付きベベルフレームを装着したダイアログ

ウィンドウとダイアログに装着する 2 種類のフレームを作成する関数を追加します。

例 3.70. ウィンドウ/ダイアログに装着するフレームの作成

// helloworld アプリケーションクラスの定義
SFMTYPEDEFCLASS(helloworld)  //  便利な型を生成するマクロ
class helloworld : public SFYApplication {

    SFMSEALCOPY(helloworld)  // インスタンスのコピーを禁止するマクロ
private:
    MyWindowSmp _myWindow;
    ItsWindowSmp _itsWindow;
    SFZTextMenuSmp _textMenu;
    TabWindowSmp _tabWindow;
    SFZSoftKeyControlSmp _softkey;

    // *** 太字が追加/修正部分

    // SFZTitlePlainFrame のスマートポインタ(ウィンドウ用フレーム)
    SFZTitlePlainFrameSmp _windowFrame;

    // SFZTitleBevelFrame のスマートポインタ(ダイアログ用フレーム)
    SFZTitleBevelFrameSmp _dialogFrame;

public:
    static SFCInvokerPtr Factory(Void);
private:
    explicit helloworld(Void) static_throws;
    virtual ~helloworld(Void);
    SFCError MakeMy(Void);
    SFCError MakeMenu(Void);
    SFCError MakeIts(Void);
    SFCError MakeTab(Void);
    SFCError MakeSoftMenu(UInt32 key);

    // タイトルテキストを設定できるように引数を拡張する

    // メッセージダイアログを作成する関数
    SFCError MakeColorDialog(SFXWideStringConstRef title, UserColorConstRef color);

    // ウィンドウ用フレームを作成する関数
    SFCError MakeWindowFrame(SFXWideStringConstRef title);

    // ダイアログ用フレームを作成する関数
    SFCError MakeDialogFrame(SFXWideStringConstRef title);

    SFCError RegisterSoftText(Void);
    Void SetMenuColors(UserColorConstRef color);
    SFXRectangle GetContentBound(Void) const;

    XANDLER_DECLARE_VOIDRENDER(OnRenderRequest)  // 描画ハンドラ
    XANDLER_DECLARE_BOOLEVENT(OnKey)             // キーハンドラ
    XANDLER_DECLARE_VOIDRESULT(OnMenuResult)     // 結果ハンドラ
    XANDLER_DECLARE_VOIDEVENT(OnSoftKey)         // ソフトキーハンドラ
    XANDLER_DECLARE_VOIDEVENT(OnMenuSoftKey)     // ソフトキーハンドラ
    XANDLER_DECLARE_VOIDEVENT(OnWindowSoftKey)   // ソフトキーハンドラ 

    // ウィンドウのキーハンドラ
    XANDLER_DECLARE_BOOLEVENT(OnWindowKey)

    // ダイアログの結果ハンドラ
    XANDLER_DECLARE_VOIDRESULT(OnDialogResult)
};

// ウィンドウ用フレームを作成する関数
SFCError helloworld::MakeWindowFrame(SFXWideStringConstRef title)
{
    SFCError error(SFERR_NO_ERROR);

    // タイトル付きプレーンフレームを作成する
    if ((_windowFrame = SFZTitlePlainFrame::NewInstance(&error)) != null) {

        // フレームのタイトルテキストを設定する
        error = _windowFrame->SetText(title);

        if (error == SFERR_NO_ERROR) {

            // フレームの影を「なし」に設定する
            _windowFrame->SetShadowEnable(false);

            // 通常、フレームの状態は「可視+活性+操作可能+フォーカス」に設定する
            _windowFrame->SetState(true, true, true, true);
        }
    }
    return error;
}

// ダイアログ用フレームを作成する関数
SFCError helloworld::MakeDialogFrame(SFXWideStringConstRef title)
{
    SFCError error(SFERR_NO_ERROR);

    // タイトル付きベベルフレームを作成
    if ((_dialogFrame = SFZTitleBevelFrame::NewInstance(&error)) != null) {

        // フレームのタイトルテキストを設定する
        error = _dialogFrame->SetText(title);

        if (error == SFERR_NO_ERROR) {

            // 通常、フレームの状態は「可視+活性+操作可能+フォーカス」に設定する
            _dialogFrame->SetState(true, true, true, true);
        }
    }
    return error;
}

ウィンドウとダイアログにフレームを装着します。

クリアキー(AVK_CLR)が押下されると、自身を閉じるように キーハンドラ OnWindowKey と結果ハンドラ OnDialogResult を登録します。

例 3.71. ウィンドウとダイアログへのフレーム装着

// MyWindow 作成
SFCError helloworld::MakeMy(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // *** 太字が追加/修正部分

    // フレームを作成する
    if ((error = MakeWindowFrame("MyWindow")) == SFERR_NO_ERROR) {

        // MyWindow インスタンスを作成する
        if ((_myWindow = MyWindow::NewInstance(&error)) != null) {

            // MyWindow の親をアプリケーションクラス(ルート)に設定する
            error = _myWindow->SetParent(GetThis());

            if (error == SFERR_NO_ERROR) {

                // MyWindow にフレームを装着する
                error = _myWindow->SetFrame(_windowFrame);

                if (error == SFERR_NO_ERROR) {

                    error = _myWindow->RegisterHandler(
                        SFXEventRange(SFEVT_RESPONDER_SOFTKEY, SFEVT_RESPONDER_SOFTKEY, SFP16_BEGIN, SFP16_END),
                        XANDLER_INTERNAL(OnWindowSoftKey)
                    );

                    if (error == SFERR_NO_ERROR) {

                        // キーハンドラを登録する
                        error = _myWindow->RegisterHandler(
                            SFXEventRange(SFEVT_KEY, SFEVT_KEY, SFP16_BEGIN, SFP16_END),
                            XANDLER_INTERNAL(OnWindowKey)
                        );

                        if (error == SFERR_NO_ERROR) {

                            // フレームの実領域をコンテント領域に設定する
                            // ※ 自動的に、ウィンドウの実領域はフレームの実領域からフレームマージン分だけ縮小した領域に設定される
                            _windowFrame->SetRealBound(GetContentBound());

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

                            // ソフトキーメニューを作成する
                            if ((error = MakeSoftMenu(KEY_MENU_WINDOW)) == SFERR_NO_ERROR) {

                                // MyWindow と作成したソフトキーメニューを関連付ける
                                error = _softkey->Bind(_myWindow, KEY_MENU_WINDOW);

                                // MyWindow を最前面に移動する
                                // ※ フレームも自動的に最前面に移動する
                                _myWindow->ToFront();

                                // MyWindow 内のコントロールを作成する
                                _myWindow->Make();
                            }
                        }
                    }
                }
            }
        }
    }
    return error;
}

// ItsWindow 作成
SFCError helloworld::MakeIts(Void)
{
    // ...(省略)...

    if ((error = MakeWindowFrame("ItsWindow")) == SFERR_NO_ERROR) {

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

// TabWindow 作成
SFCError helloworld::MakeTab(Void)
{
    // ...(省略)...

    if ((error = MakeWindowFrame("TabWindow")) == SFERR_NO_ERROR) {

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

// メッセージダイアログを作成する関数
SFCError helloworld::MakeColorDialog(SFXWideStringConstRef title, UserColorConstRef color)
{
    SFZMessageDialogSmp dlg;
    SFCError error(SFERR_NO_ERROR);

    // フレームを作成する
    if ((error = MakeDialogFrame(title)) == SFERR_NO_ERROR) {

        // メッセージダイアログを作成する
        if ((dlg = SFZMessageDialog::NewInstance(&error)) != null) {

            // 親をアプリケーションクラス(ルート)に設定する
            error = dlg->SetParent(GetThis());

            if (error == SFERR_NO_ERROR) {

                // メッセージダイアログにフレームを装着する
                error = dlg->SetFrame(_dialogFrame);

                if (error == SFERR_NO_ERROR) {

                    // メッセージダイアログに結果ハンドラを登録する
                    error = dlg->RegisterHandler(
                        SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END),
                        XANDLER_INTERNAL(OnDialogResult)
                    );

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

                    // ダイアログの実領域にダイアログに最適な領域を設定する
                    // ダイアログの最適な領域はコンテント領域をヒント領域として計算され中心に整列される
                    // ※ フレームの実領域はダイアログの実領域からフレームマージン分だけ拡大した領域として自動的に設定される
                    dlg->SetRealBound(dlg->GetSuitableBound(GetContentBound(), SFYResponder::HORIZONTAL_CENTER, SFYResponder::VERTICAL_MIDDLE));

                    dlg->SetState(true, true, true, true);

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

                    // メッセージダイアログを最前面に移動する
                    // ※ フレームも自動的に最前面に移動する
                    dlg->ToFront();
                }
            }
        }
    }
    return error;
}

// テキストメニューの結果ハンドラの実装
XANDLER_IMPLEMENT_VOIDRESULT(helloworld, OnMenuResult, invoker, reason, result)
{
    // ...(省略)...

    switch (reason) {
        case SFP16_RESULT_OK:
            TRACE("'%S' is selected", _textMenu->GetItemText(static_cast<SInt16>(result)).GetCString());
            switch (result) {
                case 0:
                case 1:
                case 2:
                case 3: {
                    SetMenuColors((color[result]));

                    // メッセージダイアログを作成する
                    // * 配色の名前(フレームのタイトルテキスト)を引数に与える
                    MakeColorDialog(_textMenu->GetItemText(result), (color[result]));

                    break;
                }

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

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

    }
    return;
}

ウィンドウを閉じる(終了する)コードを MyWindow のキーハンドラとソフトキーハンドラ、メッセージダイアログの結果ハンドラに実装します。

例 3.72. ウィンドウを閉じる

// MyWindow のキーハンドラ
XANDLER_IMPLEMENT_BOOLEVENT(helloworld, OnWindowKey, invoker, event)
{
    // invoker: MyWindow

    Bool result(false);

    switch (event.GetP16()) {

        case AVK_CLR:

            // ウィンドウを閉じる
            // ※ フレームはウィンドウから自動的に切り離され見えなくなる(フレームを閉じる操作は不要)
            invoker->Terminate();

            result = true;
            break;
    }

    return result;
}

// メッセージダイアログの結果ハンドラ
XANDLER_IMPLEMENT_VOIDRESULT(helloworld, OnDialogResult, invoker, reason, result)
{
    unused(reason);
    unused(result);

    // メッセージダイアログを閉じる
    // ※ フレームはダイアログから自動的に切り離され見えなくなる(フレームを閉じる操作は不要)
    invoker->Terminate();

    return;
}

[Note] 注意

MyWindow には 2 種類キーハンドラが登録されています。

  1. MyWindow クラスのコンストラクタ内で登録された OnKey キーハンドラ
  2. MyWindow インスタンス生成後に helloworld アプリケーションクラスで登録された OnWindowKey キーハンドラ

MyWindow 内でキーイベントが発生すると、 後に登録された OnWindowKey キーハンドラの方が OnKey キーハンドラよりも先に呼び出されます。

[Tip] 複数登録されたキーハンドラの呼び出し順序

レスポンダに 2 つ以上のキーハンドラが登録された場合、キーイベントが発生すると、 最後に登録されたキーハンドラから順に呼び出されます。

参照: キーイベント[SFEVT_KEY から SFEVT_KEY_HOOK_RELEASE]

シミュレータでの実行結果は以下の通りです。

図 3.47. タイトル付きプレーンフレームを装着したウィンドウ

タイトル付きプレーンフレームを装着したウィンドウ

図 3.48. タイトル付きベベルフレームを装着したダイアログ

タイトル付きベベルフレームを装着したダイアログ

参照: フレーム