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

9.2. イベント ハンドラ

アプリの開始や停止・中断・再開、キー入力などのイベントは、トレーサによって適切なレスポンダへ通知されます。

そして、イベント ハンドラと呼ばれる関数によってイベント毎の処理が自動的に行われます。

関連情報 : トレーサ

9.2.1. イベント ハンドラの宣言

イベント ハンドラは HANDLER_DECLARE_ で始まるマクロを使って宣言します。

引数にはハンドラ名を設定します。

関連情報 : GUI フレームワーク用マクロ : イベント ハンドラ宣言用マクロ

表 9.3. イベント ハンドラ宣言用マクロ( Void 型 )

マクロ 意味
HANDLER_DECLARE_VOIDRENDER 描画ハンドラ
HANDLER_DECLARE_VOIDSTART アプリ開始ハンドラ
HANDLER_DECLARE_VOIDSTOP アプリ終了ハンドラ
HANDLER_DECLARE_VOIDRESUME レジューム ハンドラ
HANDLER_DECLARE_VOIDSUSPEND サスペンド ハンドラ
HANDLER_DECLARE_VOIDDIALOG ダイアログ ハンドラ
HANDLER_DECLARE_VOIDMENU メニュー ハンドラ
HANDLER_DECLARE_VOIDCONTROL コントロール ハンドラ
HANDLER_DECLARE_VOIDVOID 汎用ハンドラ
HANDLER_DECLARE_VOIDEVENT 汎用ハンドラ

例 9.4. 描画ハンドラの宣言

// MyWindow クラスの定義
SFMTYPEDEFCLASS(MyWindow)
class MyWindow : public SFRTitleWindow {
    SFMSEALCOPY(MyWindow)
public:
    MyWindow(Void) static_throws;
    virtual ~MyWindow(Void)
    
    // 描画ハンドラの宣言
    // 引数はハンドラ名
    HANDLER_DECLARE_VOIDRENDER(OnRenderContent)
};

表 9.4. イベント ハンドラ宣言用マクロ( Bool 型 )

マクロ 意味
HANDLER_DECLARE_BOOLSTART アプリ開始ハンドラ
HANDLER_DECLARE_BOOLSTOP アプリ終了ハンドラ
HANDLER_DECLARE_BOOLRESUME レジューム ハンドラ
HANDLER_DECLARE_BOOLSUSPEND サスペンド ハンドラ
HANDLER_DECLARE_BOOLDIALOG ダイアログ ハンドラ
HANDLER_DECLARE_BOOLMENU メニュー ハンドラ
HANDLER_DECLARE_BOOLCONTROL コントロール ハンドラ
HANDLER_DECLARE_BOOLVOID 汎用ハンドラ
HANDLER_DECLARE_BOOLEVENT 汎用ハンドラ

例 9.5. キー ハンドラの宣言

// MyWindow クラスの定義
SFMTYPEDEFCLASS(MyWindow)
class MyWindow : public SFRTitleWindow {
    SFMSEALCOPY(MyWindow)
public:
    MyWindow(Void) static_throws;
    virtual ~MyWindow(Void)
    
    // キー ハンドラの宣言
    // 引数はハンドラ名
    HANDLER_DECLARE_BOOLEVENT(OnKey)
};
[Note] ハンドラ宣言マクロによって …

ハンドラ関数へのポインターとハンドラ識別番号 ( リファレンス値 ) が生成されます。

9.2.2. イベント ハンドラの実装

イベント ハンドラは HANDLER_IMPLEMENT_ で始まるマクロを使って実装します。

第 1 引数は所属クラス名、第 2 引数はハンドラ名です。第 3 引数以降はハンドラによって異なります。

関連情報 : GUI フレームワーク用マクロ : イベント ハンドラ実装用マクロ

表 9.5. イベント ハンドラ実装用マクロ( Void 型 )

マクロ 意味 第 3 引数 第 4 引数 第 5 引数
HANDLER_IMPLEMENT_VOIDRENDER 描画ハンドラ graphics (グラフィック オブジェクト) なし なし
HANDLER_IMPLEMENT_VOIDSTART アプリ開始ハンドラ environment なし なし
HANDLER_IMPLEMENT_VOIDSTOP アプリ終了ハンドラ quitable なし なし
HANDLER_IMPLEMENT_VOIDRESUME レジューム ハンドラ environment なし なし
HANDLER_IMPLEMENT_VOIDSUSPEND サスペンド ハンドラ reason info なし
HANDLER_IMPLEMENT_VOIDDIALOG ダイアログ ハンドラ result dialog ( へのポインター ) なし
HANDLER_IMPLEMENT_VOIDMENU メニュー ハンドラ result menu ( へのポインター ) なし
HANDLER_IMPLEMENT_VOIDCONTROL コントロール ハンドラ result control ( へのポインター ) なし
HANDLER_IMPLEMENT_VOIDVOID 汎用ハンドラ なし なし なし
HANDLER_IMPLEMENT_VOIDEVENT 汎用ハンドラ event ( イベント オブジェクト ) なし なし

例 9.6. 描画ハンドラの実装

// 第 1 引数 : 所属クラス、第 2 引数 : ハンドラ名、第 3 引数 : グラフィック オブジェクト
HANDLER_IMPLEMENT_VOIDRENDER(MyWindow, OnRenderContent, graphics)
{
    // 文字列 "Hello World" を描画する
    graphics->DrawText("Hello World", GetContentWorld());
    return;
}

表 9.6. イベント ハンドラ実装用マクロ( Bool 型 )

マクロ 意味 第 3 引数 第 4 引数 第 5 引数
HANDLER_IMPLEMENT_BOOLSTART アプリ開始ハンドラ environment なし なし
HANDLER_IMPLEMENT_BOOLSTOP アプリ終了ハンドラ quitable なし なし
HANDLER_IMPLEMENT_BOOLRESUME レジューム ハンドラ environment なし なし
HANDLER_IMPLEMENT_BOOLSUSPEND サスペンド ハンドラ reason info なし
HANDLER_IMPLEMENT_BOOLDIALOG ダイアログ ハンドラ result dialog ( へのポインター ) なし
HANDLER_IMPLEMENT_BOOLMENU メニュー ハンドラ result menu ( へのポインター ) なし
HANDLER_IMPLEMENT_BOOLCONTROL コントロール ハンドラ result control ( へのポインター ) なし
HANDLER_IMPLEMENT_BOOLVOID 汎用ハンドラ なし なし なし
HANDLER_IMPLEMENT_BOOLEVENT 汎用ハンドラ event ( イベント オブジェクト ) なし なし

例 9.7. キー ハンドラの実装

//ウィンドウが最前面にあるときにキーが押されると実行される
第 1 引数 : 所属クラス、第 2 引数 : ハンドラ名、第 3 引数 : イベント値
HANDLER_IMPLEMENT_BOOLEVENT(MyWindow, OnKey, event)
{
    // 押されたキーの種類に応じて分岐する
    switch (event.GetP16()) {
        case AVK_CLR: // クリアー キーの場合
           // ウィンドウを閉じる
            return Invoke(SFXEvent(SREVT_RESPONDER_TERMINATE,
                                   SRP16_TERMINATE_INVOKE, true));

        case AVK_1:   // 1 キーの場合

            ...

            return true;  // 押されたキーの処理したときは true を返す
    }
    return false;         // 押されたキーの処理しなかったときは false を返す
}

9.2.3. イベント ハンドラの登録

ハンドラは RegisterHandler 関数で登録し、UnregisterHandler 関数で破棄します。

ひとつのイベントに 2 つ以上のイベント ハンドラが登録されたときは、最後に登録されたイベント ハンドラが有効となります。

■ イベント ハンドラの登録時に必要な設定情報

  1. イベント タイプと第 1 パラメーター : BREW イベントと同様。
  2. イベント処理のタイミング : イベントを処理するのは、 イベントを子階層へ通知する前(HANDLER_BEFORE)かそれとも後(HANDLER_AFTER)か。

図 9.1. イベントの流れ

イベントの流れ

表 9.7. イベント処理のタイミング

処理のタイミング 解説
HANDLER_BEFORE 子レスポンダへイベントを通知する前に、親レスポンダでイベントを処理します。
HANDLER_AFTER 子レスポンダへイベントを通知して処理してから、親レスポンダでイベントを処理します。
[Note] イベント 処理のタイミング

レスポンダ(UI コンポーネント)は、最背面にあるレスポンダ(親レスポンダ)からその前面に位置するレスポンダ(子レスポンダ)へと順に描画する必要があるので、 描画ハンドラの登録ではイベント処理のタイミングは HANDLER_BEFORE を指定します。

一方、キー イベントは最前面のレスポンダ(子レスポンダ)からその背面に位置するレスポンダ(親レスポンダ)の順に処理する必要があるので、 キー ハンドラの登録では HANDLER_AFTER を指定します。

親レスポンダと子レスポンダの生成と破棄の順序関係から、レジューム イベントとサスペンド イベントに対するハンドラ登録では、 それぞれ HANDLER_BEFOREHANDLER_AFTER を指定します。 アプリの開始イベントと終了イベントに関しても、同じ理由でそれぞれ HANDLER_BEFOREHANDLER_AFTER を指定します。

例 9.8. ハンドラの型

Bool  (*SFRResponderSPP)  (SFXEventConstRef event, VoidPtr reference);

例 9.9. 子階層よりも前に処理するハンドラの登録

SFRResponderPtr responder;
SFCError error;

error = responder->RegisterHandler(SREVT_CONTROL, 
                                   HANDLER_BEFORE, 
                                   HANDLER_FUNCTION(OnControl));

例 9.10. 子階層よりも後に処理するハンドラの登録

SFRResponderPtr responder;
SFCError error;

error = responder->RegisterHandler(SFEVT_KEY, 
                                   SFEVT_KEY_RELEASE, 
                                   AVK_SELECT, 
                                   HANDLER_AFTER, 
                                   HANDLER_FUNCTION(OnKey));
[Note] HANDLER_FUNCTION の役割

HANDLER_DECLARE_ で始まるハンドラ宣言マクロの引数を HANDLER_FUNCTION マクロの引数とすることで、 ハンドラへの関数ポインターとハンドラ識別番号 ( リファレンス値 ) が RegisterHandler 関数に渡されます。

キー イベントをハンドルしたことにするには以下のように記述します。

例 9.11. キー イベントをハンドルしたことにする方法

SFRResponderPtr responder;
SFCError error;

error = responder->RegisterHandler(SFEVT_KEY, 
                                   SFEVT_KEY_RELEASE, 
                                   HANDLER_BEFORE, 
                                   HANDLER_NULL);
[Warning] 警告
上記コードでキー イベントをハンドルしたことにできるかどうかはトレーサの設定も影響します。

ハンドラは最も新しく登録されたものが有効です。以下の A と B のサンプル コードは動作が異なります。

例 9.12. ハンドラの登録 A

SFRResponderPtr responder;

responder->RegisterHandler(SFEVT_KEY, 
                           HANDLER_AFTER, 
                           HANDLER_FUNCTION(OnKey));
responder->RegisterHandler(SFEVT_KEY, 
                           SFEVT_KEY_RELEASE, 
                           HANDLER_AFTER, 
                           HANDLER_FUNCTION(OnHeld1));
responder->RegisterHandler(SFEVT_KEY, 
                           SFEVT_KEY_RELEASE, 
                           HANDLER_AFTER, 
                           HANDLER_FUNCTION(OnHeld2));

例 9.13. ハンドラの登録 B

SFRResponderPtr responder;

responder->RegisterHandler(SFEVT_KEY, 
                           SFEVT_KEY_RELEASE, 
                           HANDLER_AFTER, 
                           HANDLER_FUNCTION(OnHeld1));
responder->RegisterHandler(SFEVT_KEY, 
                           SFEVT_KEY_RELEASE, 
                           HANDLER_AFTER, 
                           HANDLER_FUNCTION(OnHeld2));
responder->RegisterHandler(SFEVT_KEY, 
                           HANDLER_AFTER, 
                           HANDLER_FUNCTION(OnKey));