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

9.11. メニュー

メニューは、いくつかの項目をリストして表示し、ユーザに選択させるレスポンダです。 メニューの生成方法や使用方法はウィンドウの場合と ほとんど同じですが、テキスト メニューなどは生成するだけで すぐに使えるように実装されています。

9.11.1. メニューの生成

メニューを表示するには生成したいメニューのインスタンスを new 演算子で生成します。

以下にテキスト メニューを表示するサンプル コードを示します。

SFMTYPEDEFCLASS(Demo)
class Demo : public SFRApplication {
  public:
    static inline SFCInvokerPtr Constructor(Void)
    {
      return(new Demo());
    }
	
  private:
    inline Demo(Void)
    {
      SFRMenuPtr     menu;
      SFUWideString  item[]  = {"item0", "item1", "item2"};

      if (Exception() == NO_ERROR) {
        menu = new SFRTextMenu(this, SFURect(10, 10, 100, 100), "Sample", item, sizearray(item));
        if (menu != NULL) {
          if (Exception(menu->Exception()) != NO_ERROR) {
            delete menu;
          }
        }
        else {
          Exception(ENOMEMORY);
        }
      }
      return;
    }
	
    virtual inline ~Demo(Void)
    {
      return;
    }
};

9.11.2. イベントの処理

上記コードではテキスト メニューが表示され、セレクト キーが押されるか クリア キーが押されるとメニューが閉じるというデフォルトの動作をします。 テキスト メニューの動作をカスタマイズするには、SREVT_MENU イベントを 受け取るハンドラを登録します。以下にサンプル コードを示します。

SFMTYPEDEFCLASS(Demo)
class Demo : public SFRApplication {
  public:
    static inline SFCInvokerPtr Constructor(Void)
    {
      return(new Demo());
    }
	
  private:
    inline Demo(Void)
    {
      SFRMenuPtr     menu;
      SFUWideString  item[]  = {"item0", "item1", "item2"};

      if (Exception() == NO_ERROR) {
        menu = new SFRTextMenu(this, SFURect(10, 10, 100, 100), "Sample", item, sizearray(item));
        if (menu != NULL) {
          if (Exception(menu->Exception()) == NO_ERROR) {
            Exception(menu->RegisterHandler(SREVT_MENU, HANDLER_BEFORE, Menu_static, this));
          }
          else {
            delete menu;
          }
        }
        else {
          Exception(ENOMEMORY);
        }
      }
      return;
    }
	
    virtual inline ~Demo(Void)
    {
      return;
    }
	
    static inline Bool Menu_static(ConstSFUEventRef event, VoidPtr responder)
    {
      DemoPtr(responder)->Menu_handler(event.p16(), SFRTextMenuPtr(event.p32()));
      return(TRUE);
    }
	
    inline Void Menu_handler(UInt16 select, SFRTextMenuPtr menu)
    {
      switch (select) {
        case SRP16_ESCAPE:
          // something to do
          break;
        /*case SRP16_CANCEL:
          break;*/
        default:
          // something to do
          break;
      }
      menu->MenuHandler();
      // 以下の方法でも良いです。
      //menu->Invoke(SFUEvent(SREVT_RESPONDER_TERMINATE, SRP16_TERMINATE_INVOKE, TRUE));
      return;
    }
};

上記コードではセレクト キーが押されたときもしくはクリア キーに よりメニューがエスケープされたときに Menu_handler 関数が 呼び出されます。Menu_handler 関数には選択されている項目の インデックスかキャンセルの理由を表す数値と、オブジェクトへの ポインタが渡されますので、それを利用して処理を行います。

メニューが選択されたときはインデックスの番号が、クリア キー が押されたときは SRP16_ESCAPE が、その他の方法でメニューが キャンセルされた場合は SRP16_CANCEL が上記サンプル コードの select 変数に渡されます。

また、ハンドラを登録したときにメニューのデフォルト動作を オーバーライトしているので明示的にメニューを破棄しなければ メニューが閉じません。

破棄する方法はレスポンダのそれと同じですが、ダイアログと 同じように方法が2通りあります。一つは、メニューのデフォルト ハンドラを呼び出す方法。もう一つは、SREVT_RESPONDER_TERMINATE イベントを メニューに送信する方法です。

[Note] 注意

選択項目のインデックスのうち 65000 番以降はキャンセルの 理由を区別するために使用されますので、インデックスに 使用できません。つまり、メニュー項目は多くても 65000 未満で なければなりません。

9.11.3. メニューの種類

メニューは標準で1種類定義されており SFRTextMenu がそれです。 メニューは継承して使用することはできません。 用意されているメニューとまったく異なるメニューを定義する場合は、 SFRMenu から継承します。