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

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

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

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

図 9.29. 動作例

動作例

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

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

例 9.42. 宣言

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

    ...
private:
    SFCError Make(Void);

    // ウィンドウ用の描画ハンドラを宣言します。
    XANDLER_DECLARE_VOIDRENDER(OnRenderRequest)
};

例 9.43. 実装

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)));
                _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.12.2. ウィンドウ内部に描画する(2)

図 9.30. 動作例

動作例

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

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

例 9.44. 宣言

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

    ...
protected:

    // 描画要求時に呼び出される仮想関数をオーバーライトします。
    virtual Void HandleRenderRequest(SFXGraphicsPtr graphics) const;
};

例 9.45. 実装

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.12.3. 実領域よりも大きな仮想領域をスクロールする

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

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

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

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

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

例 9.46. 宣言

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

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

例 9.47. 実装

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;
}