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

9.11. ウィンドウ(応用編)

ウィンドウ内部の描画や仮想領域の扱い方などについて解説します。

9.11.1. ウィンドウ内部に描画する(1)

図 9.31. 動作例

動作例

ウィンドウ(SFZWindow)の上にコントロールやコンテナを配置する以外に、ウィンドウ内部に直接テキストやイメージを描画できます。

汎用ウィンドウ(SFZWindow)に外部から描画を行うには、 描画ハンドラを登録します。

例 9.50. 宣言

SFMTYPEDEFCLASS(USRApplication)
class USRApplication : public SFYApplication {
    SFMSEALCOPY(USRApplication)
private:
    SFZWindowSmp _window;

    ...
private:
    SFCError Make(Void);

    // ウィンドウ用の描画ハンドラ
    XANDLER_DECLARE_VOIDRENDER(OnRenderRequest)
};

例 9.51. 実装

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

    // ウィンドウを作成する
    if ((_window = SFZWindow::NewInstance(&error)) != null) {

        // ウィンドウの親レスポンダを USRApplication に設定する
        error = _window->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // ウィンドウに描画ハンドラを登録する
            error = _window->RegisterHandler(
                SFXEventRange(SFEVT_RESPONDER_RENDER, SFEVT_RESPONDER_RENDER, SFP16_RENDER_REQUEST, SFP16_RENDER_REQUEST),
                XANDLER_INTERNAL(OnRenderRequest)
            );
            if (error == SFERR_NO_ERROR) {

                // ウィンドウの実領域を計算して設定する
                _window->SetRealBound(_window->GetSuitableBound(GetLocalBound().Deflate(10, 10)));

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

                // ウィンドウを最前面に移動する
                _window->ToFront();
            }
        }
    }
    return error;
}

XANDLER_IMPLEMENT_VOIDRENDER(USRApplication, OnRenderRequest, invoker, reason, graphics)
{
    SFXRectangle local;
    SInt16 i;
    SInt16 j;

    local.Set(_window->GetLocalBound());

    // チェック模様を描画する
    for (j = 0; j < local.GetBottom(); j += 10) {
        for (i = 0; i < local.GetRight(); i += 10) {
            if ((i + j) / 10 % 2 == 0) {
                graphics->FillRectangle(SFXRectangle(i, j, 10, 10), SFXRGBColor(0xCC, 0xFF, 0xCC, 0x00));
            }
            else {
                graphics->FillRectangle(SFXRectangle(i, j, 10, 10), SFXRGBColor(0xAA, 0xDD, 0xAA, 0x00));
            }
        }
    }
    return;
}

9.11.2. ウィンドウ内部に描画する(2)

図 9.32. 動作例

動作例

ウィンドウ(SFZWindow)の上にコントロールやコンテナを配置する以外に、 ウィンドウ内部に直接テキストやイメージを描画できます。

ユーザー定義ウィンドウ自身で描画を行うには、 描画ハンドラを登録するよりも仮想関数をオーバーライドします。

例 9.52. 宣言

SFMTYPEDEFRESPONDER(USRWindow)
class USRWindow : public SFZWindow {
    SFMSEALRESPONDER(USRWindow)
    SFMRESPONDERINSTANTIATEFOUR(USRWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)

    ...
protected:

    // 描画イベントを受信すると呼び出される仮想関数をオーバーライドする
    virtual Void HandleRenderRequest(SFXGraphicsPtr graphics) const;
};

例 9.53. 実装

Void USRWindow::HandleRenderRequest(SFXGraphicsPtr graphics) const
{
    SFXRectangle local;
    SInt16 i;
    SInt16 j;

    local.Set(GetLocalBound());

    // チェック模様を描画する
    for (j = 0; j < local.GetBottom(); j += 10) {
        for (i = 0; i < local.GetRight(); i += 10) {
            if ((i + j) / 10 % 2 == 0) {
                graphics->FillRectangle(SFXRectangle(i, j, 10, 10), SFXRGBColor(0xCC, 0xFF, 0xCC, 0x00));
            }
            else {
                graphics->FillRectangle(SFXRectangle(i, j, 10, 10), SFXRGBColor(0xAA, 0xDD, 0xAA, 0x00));
            }
        }
    }
    return;
}

9.11.3. 実領域よりも大きく設定された仮想領域をスクロールする

図 9.33. 動作例(左:スクロール前、右:スクロール後)

動作例(左:スクロール前、右:スクロール後)

仮想領域を実領域よりも大きく設定する場合、ウィンドウ内部をスクロールできます。

以下に汎用ウィンドウをそのまま用いる場合のコードを示します。

ユーザー定義ウィンドウを用いる場合でも、上記方法などを参考にほとんど同じ方法で実現できます。

例 9.54. 宣言

SFMTYPEDEFCLASS(USRApplication)
class USRApplication : public SFYApplication {
    SFMSEALCOPY(USRApplication)
private:
    SFZWindowSmp _window;

    ...
private:
    SFCError Make(Void);
    XANDLER_DECLARE_VOIDRENDER(OnRenderRequest)
};

例 9.55. 実装

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

    if ((_window = SFZWindow::NewInstance(&error)) != null) {
        error = _window->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {
            error = _window->RegisterHandler(
                SFXEventRange(SFEVT_RESPONDER_RENDER, SFEVT_RESPONDER_RENDER, SFP16_RENDER_REQUEST, SFP16_RENDER_REQUEST),
                XANDLER_INTERNAL(OnRenderRequest)
            );
            if (error == SFERR_NO_ERROR) {
                _window->SetRealBound(_window->GetSuitableBound(GetLocalBound().Deflate(10, 10)));

                // 仮想領域を下に 100 ピクセルだけ拡張して設定する
                _window->SetVirtualBound(SFXRectangle(_window->GetVirtualBound()).AddBottom(100));

                // スクロールの移動量を設定する
                _window->SetScrollStep(5);

                // スクロールが終端に達したときに自動的に最初に戻るかどうかを設定する
                _window->SetScrollRepeat(true);

                _window->SetState(true, true, true, true);
                _window->ToFront();
            }
        }
    }
    return error;
}

XANDLER_IMPLEMENT_VOIDRENDER(USRApplication, OnRenderRequest, invoker, reason, graphics)
{
    SFXRectangle local;
    SInt16 i;
    SInt16 j;

    local.Set(_window->GetLocalBound());
    for (j = 0; j < local.GetBottom(); j += 10) {
        for (i = 0; i < local.GetRight(); i += 10) {
            if ((i + j) / 10 % 2 == 0) {
                graphics->FillRectangle(SFXRectangle(i, j, 10, 10), SFXRGBColor(0xCC, 0xFF - j, 0xCC + j, 0x00));
            }
            else {
                graphics->FillRectangle(SFXRectangle(i, j, 10, 10), SFXRGBColor(0xAA, 0xDD - j, 0xAA + j, 0x00));
            }
        }
    }
    return;
}