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

3.2. ウィンドウ

3.2.1. ウィンドウの定義と実装

SophiaFramework AppWizard が生成した HelloWorld アプリのコードをカスタマイズします。

1 キー が押されると、ウィンドウを作成しウィンドウに文字列 "Hello World" を表示します。

クリア キーが押されると、ウィンドウを閉じます。

図 3.1. ウィンドウ内に文字列 "HelloWorld" を表示する HelloWorld アプリ

ウィンドウ内に文字列 "HelloWorld" を表示する HelloWorld アプリ

SFZWindow を継承したカスタム ウィンドウ MyWindow の定義を行います。

例 3.6. カスタム ウィンドウ の定義

// SFZWindow から継承します
SFMTYPEDEFRESPONDER(MyWindow)
class MyWindow : public SFZWindow
{
    SFMSEALRESPONDER(MyWindow)
    SFMRESPONDERINSTANTIATEFOUR(MyWindow, SFZWindow, SFYContainer, SFYWidget, SFYResponder)
public:
    // このレスポンダのタイプを定義します。
    // 小文字と記号からのみなるタイプはSophiaFramework により予約されています。
    enum CodeEnum {
        CODE_TYPE = four_char_code('M', 'W', 'N', 'D')
    };
public:
    static MyWindowSmp NewInstance(SFCErrorPtr exception = null);
protected:
    explicit MyWindow(Void) static_throws;
    virtual ~MyWindow(Void);
    virtual Void HandleRenderRequest(SFXGraphicsPtr graphics) const; // 描画の仮想関数を継承します
    XANDLER_DECLARE_BOOLEVENT(OnKey) // キー ハンドラ
};

HelloWorld クラスのメンバに、先ほど定義した MyWindow を宣言します。

例 3.7. HelloWorld クラス定義の変更

SFMTYPEDEFCLASS(HelloWorld)
class HelloWorld : public SFYApplication
{
    SFMSEALCOPY(HelloWorld)
private:
    // *** 太字が追加部分

    MyWindowSmp _myWindow; // MyWindowクラスのスマートポインタ
public:
    static SFCInvokerPtr Factory(Void);
private:
    explicit HelloWorld(Void) static_throws;
    virtual ~HelloWorld(Void);

    SFCError Make(Void); // ウィンドウ作成

    XANDLER_DECLARE_VOIDRENDER(OnRenderRequest)
    XANDLER_DECLARE_BOOLEVENT(OnKey)
};
[Note] スマートポインタ

クラス名の語尾に Smp を付加することで、メモリ管理の便利なスマートポインタを用いることができます。

スマートポインタは、SFMTYPEDEFTYPE で定義されます。クラス定義の前にある SFMTYPEDEFRESPONDER マクロや SFMTYPEDEFCLASS マクロは内部で SFMTYPEDEFTYPE マクロを呼び出しています。

MyWindow の コンストラクタ、デストラクタ、インスタンス作成、ハンドラの実装を行います。

例 3.8. カスタム ウィンドウ の実装

// コンストラクタ
MyWindow::MyWindow(Void) static_throws
{
    // このレスポンダのタイプを設定します。
    if (static_try()) {
        SetType(CODE_TYPE);
    }
    // キーハンドラの登録
    if (static_try()) {
        static_throw(RegisterHandler(
            SFXEventRange(SFEVT_KEY, SFEVT_KEY, SFP16_BEGIN, SFP16_END),
            XANDLER_INTERNAL(OnKey)
        ));
    }
}

// インスタンス作成
MyWindowSmp MyWindow::NewInstance(SFCErrorPtr exception)
{
    return static_pointer_cast<MyWindow>(Factory(:: new MyWindow, exception));
}

// デストラクタ
MyWindow::~MyWindow(Void)
{
}

// 配色定義

// 黒色
#define COLOR_BLACK                 (SFXRGBColor(0x00, 0x00, 0x00, 0x00))
// 薄緑色
#define COLOR_MY_WINDOW_BACK        (SFXRGBColor(0xCC, 0xFF, 0xCC, 0x00))

// ウィンドウの描画ハンドラ
Void MyWindow::HandleRenderRequest(SFXGraphicsPtr graphics) const
{
    // ウィンドウ全体を薄緑色に描画します。
    graphics->FillRectangle(GetLocalBound(), COLOR_MY_WINDOW_BACK);

    // 文字列 "Hello Window" を描画します。
    graphics->DrawSingleText("Hello Window", GetVirtualBound(), COLOR_BLACK);
    return;
}

// キー ハンドラ (ウィンドウが前面にあるときにキーが押されると実行されます。) 
XANDLER_IMPLEMENT_BOOLEVENT(MyWindow, OnKey, invoker, event)
{
    switch (event.GetP16()) {
        case AVK_CLR: // クリアー キーが押されたとき
            // ウィンドウを閉じます。
            invoker->Terminate();
            return true;
        case AVK_1: // 1 キーが押されたとき
            // デバッグ文字列をシミュレータのデバッグ ウィンドウに表示します。
            TRACE("1-key");
            return true;
    }
    return false;
}

[Note] GetVirtualBound 関数

仮想領域の設定をしていない場合、GetVirtualBound 関数で取得できる領域は GetLocalBound 関数で取得できる領域と等しくなります。

3.2.2. ウィンドウの作成

1 キーを押すとウィンドウが表示されるように HelloWorld クラスのキー ハンドラをカスタマイズします。

例 3.9. HelloWorld : ウィンドウの作成

// MyWindow 作成
SFCError HelloWorld::Make(Void)
{
    SFCError error(SFERR_NO_ERROR);

    if ((_myWindow = MyWindow::NewInstance(&error)) != null) {
        error = _myWindow->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {
            // ウィンドウのサイズを画面サイズから横 15 ピクセル、縦 20 ピクセル小さくしたサイズに設定します。
            _myWindow->SetRealBound(_myWindow->GetSuitableBound(GetLocalBound().Deflate(15, 20)));
            // ウィンドウの状態を設定します。
            _myWindow->SetState(true, true, true, true);
            // ウィンドウを最前面に移動します。
            _myWindow->ToFront();
        }
    }
    return error;
}

例 3.10. HelloWorld : キー ハンドラのカスタマイズ

// キー ハンドラ
XANDLER_IMPLEMENT_BOOLEVENT(HelloWorld, OnKey, invoker, event)
{
    unused(invoker);

    // キー ハンドラの処理
    switch (event.GetP16()) {
        case AVK_SELECT: // セレクト キーが押されたとき
            Terminate(); // アプリを終了する
            return true;

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

        case AVK_1: // 1 キーが押されたとき
            if (Make() != SFERR_NO_ERROR) {
                return false;
            }
        // キー イベントを処理したので true を返す
        return true;
    }
    return false; // キー イベントを処理しないときは false を返す
}

3.2.3. ウィンドウの破棄

作成した ウィンドウを破棄するには MyWindowの invokerに対して Terminate 関数を呼び出します。

例 3.11. ウィンドウの破棄

// ウィンドウを破棄する
invoker->Terminate();
[Warning] 警告

delete 演算子では破棄できません。

3.2.4. シミュレータでの実行

  1. 1 キーを押すと、ウィンドウが表示されます。
  2. 更に 1 キーを押すと、デバッグ ウィンドウに "1-key" が表示されます。
  3. クリアーキーを押すと、ウィンドウは閉じます。

図 3.2. 実行結果

実行結果

図 3.3. デバッグ ウィンドウ

デバッグ ウィンドウ
[Note] 注意
デバッグ ウィンドウは、メニューから [ 表示 ] - [ 出力ウィンドウ ] を選ぶと表示されます。