SophiaFramework UNIVERSE 5.3 |
SFYMenu クラスは、 項目のリストから 1 つの項目を選択するためのメニューを実装するための基底クラスです。
このクラスは、 操作キーまたは ESCAPE キーを押下すると、 デフォルトのキーハンドラにより、 SFYMenu は結果イベントを受信します。 また、SFYMenu は、 一定時間経過後に自動的に閉じる機能も提供します。
具象メニューとして、 テキストメニュー(SFZTextMenu)、 グリッドメニュー(SFZGridMenu)、 フレックスリストメニュー(SFZFlexListMenu)の 3 つがあります。
この節では、 テキストメニュー(SFZTextMenu)について解説します。
下図のテキストメニュー(SFZTextMenu)を作成します。
helloworld アプリケーションクラスにメニューを作成する関数を追加します。 メニューの色をまとめて設定するための構造体や関数も定義します。
例 3.45. helloworld アプリケーションクラスとカスタム色構造体の定義
// helloworld アプリケーションクラスの定義 SFMTYPEDEFCLASS(helloworld) // 便利な型を生成するマクロ class helloworld : public SFYApplication { SFMSEALCOPY(helloworld) // インスタンスのコピーを禁止するマクロ private: MyWindowSmp _myWindow; // *** 太字が追加/修正部分 // SFZTextMenu のスマートポインタ SFZTextMenuSmp _textMenu; public: static SFCInvokerPtr Factory(Void); private: explicit helloworld(Void) static_throws; virtual ~helloworld(Void); // MyWindow 作成 SFCError MakeMy(Void); // 名称を Make から MakeMy に変更する // SFZTextMenu 作成 SFCError MakeMenu(Void); // テキストメニューの色をまとめて設定する関数 Void SetMenuColors(UserColorConstRef color); XANDLER_DECLARE_VOIDRENDER(OnRenderRequest) // 描画ハンドラ XANDLER_DECLARE_BOOLEVENT(OnKey) // キーハンドラ // テキストメニューの結果ハンドラ XANDLER_DECLARE_VOIDRESULT(OnMenuResult) }; // カスタム色構造体(メニューの配色設定に利用する) SFMTYPEDEFSTRUCT(UserColor) struct UserColor { SFMTYPEDEFSTRUCT(AtomRec) struct AtomRec { // UserColor::AtomRec -> UserColor への暗黙的変換を宣言するマクロ SFMUTILITYATOMDECLARE(UserColor) SFXRGBColor::AtomRec light; SFXRGBColor::AtomRec base; SFXRGBColor::AtomRec dark; SFXRGBColor::AtomRec titleFore; SFXRGBColor::AtomRec titleBack; SFXRGBColor::AtomRec itemFore; SFXRGBColor::AtomRec itemBack; SFXRGBColor::AtomRec selFore; SFXRGBColor::AtomRec selBack; }; SFXRGBColor light; SFXRGBColor base; SFXRGBColor dark; SFXRGBColor titleFore; SFXRGBColor titleBack; SFXRGBColor itemFore; SFXRGBColor itemBack; SFXRGBColor selFore; SFXRGBColor selBack; }; // 2 つのクラスサイズが等しいことを保障する(サイズが異なる場合はコンパイルエラーとなる) SFMCONCEPTGLOBALTWO(concept_size_eq_type, UserColor, UserColor::AtomRec) // UserColor::AtomRec -> UserColor への暗黙的変換を実装するマクロ SFMUTILITYATOMIMPLEMENT(UserColor, AtomRec)
AtomRec 構造体 | |
---|---|
AtomRec 構造体とは、AtomRec 構造体が定義されるクラスまたは構造体と同じメモリ配置を持つ C 言語の POD(Plain Old Data)構造体のことです。 詳細は、RealView コード生成ツールの最適化(Sophia Cradle 社 Web サイト)を参照してください。 クラスや構造体に AtomRec 構造体を定義すると、 クラスや構造体の初期化コードのサイズと実行速度を最適化することができます。 このとき、AtomRec 構造体を定義するクラスでは仮想関数、多重継承、仮想継承を利用してはいけません。 AtomRec 構造体は、SFXEvent, SFXEventRange, 図形と色のクラスなどで利用されています。 これらのクラスでは、SFXxxxxx → SFXxxxxx::AtomRec および SFXxxxxx::AtomRec → SFXxxxxx の型変換をサポートする atomic_cast 演算子が利用可能です。 atomic_cast 演算子は、 SFMUTILITYATOMICCASTDECLARE マクロと SFMUTILITYATOMICCASTIMPLEMENT マクロを利用して宣言・実装します。 AtomRec 構造体からクラスや構造体への暗黙の型変換演算子は、 SFMUTILITYATOMDECLARE マクロと SFMUTILITYATOMIMPLEMENT マクロを利用して実装します。 |
SFMCONCEPTGLOBALTWO(concept_size_eq_type, Type_A, Type_B) マクロ | |
---|---|
SFMCONCEPTGLOBALTWO(concept_size_eq_type, Type_A, Type_B) マクロは、 Type_A 型と Type_B 型のサイズが等しいことを保証します。 Type_A 型と Type_B 型のサイズが異なる場合は、コンパイルエラーとなります。 詳細は、以下のこのマクロに関する定義を参照してください。 #define SFMCONCEPTGLOBALTWO(TYPE, ONE, TWO) \ template class static_concept_special< TYPE<ONE, TWO> >; template <typename T, typename M> class concept_size_eq_type { public: inline void constraints (void) { char c[(sizeof(T) == sizeof(M)) ? (1) : (-1)]; (void)(c); return; }// constraints // }; template <typename T> class static_concept_special { public: inline static void constraints (void) { (void)(&T::constraints); return; }// constraints // }; |
テキストメニューを作成し、 結果ハンドラで配色処理を行います。
例 3.47. テキストメニューの作成
// テキストメニューを作成する関数 SFCError helloworld::MakeMenu(Void) { SFCError error(SFERR_NO_ERROR); // テキストメニューを作成する if ((_textMenu = SFZTextMenu::NewInstance(&error)) != null) { // 親をルートに設定する error = _textMenu->SetParent(GetThis()); if (error == SFERR_NO_ERROR) { // 結果イベントを受信する結果ハンドラをテキストメニューに登録する error = _textMenu->RegisterHandler( SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END), XANDLER_INTERNAL(OnMenuResult) ); if (error == SFERR_NO_ERROR) { // テキストメニューのタイトルを設定する error = _textMenu->SetTitle("TextMenu"); if (error == SFERR_NO_ERROR) { // テキストの初期化 SFXWideString item[] = { "Elegant", "Carnival", "Dynamic", "Black", "***", "Scrollable Style", "Page Style", "***", "Sample9", "Sample10", "Sample11", "Sample12", "Sample13", "Sample14", "Sample15", "Sample16" }; // アクセスキーの初期化 // 項目 0 〜 8、項目 15 にアクセスキーがセットされる AVKType key[lengthof(item)] = { AVK_1, AVK_2, AVK_3, AVK_4, AVK_5, AVK_6, AVK_7, AVK_8, AVK_9, 0, 0, 0, 0, 0, 0, AVK_0 }; // キーアイコンの初期化 WChar icon[lengthof(item)] = { '1', '2', '3', '4', '5', '6', '7', '8', '9', ' ', ' ', ' ', ' ', ' ', ' ', '0' }; for (SInt16 i = 0; i < lengthof(item); ++i) { // 項目をまとめてテキストメニューに追加する if ((error = _textMenu->InsertLast(item[i], key[i], icon[i])) != SFERR_NO_ERROR) { break; } } // 5 番目の項目を有効フラグを false にする _textMenu->SetItemEnable(4, false); // 8 番目の項目を有効フラグを false にする _textMenu->SetItemEnable(7, false); if (error == SFERR_NO_ERROR) { // テキストメニューの←キーを使わない (サブメニューがある場合に使用されるキー) _textMenu->SetSelectLeftKey(null); // テキストメニューの→キーを使わない (サブメニューがある場合に使用されるキー) _textMenu->SetSelectRightKey(null); // テキストメニューの実領域をルートのローカル領域に設定する _textMenu->SetRealBound(GetLocalBound()); // テキストメニューの状態を「可視+活性+操作可能+フォーカス」にまとめて設定する _textMenu->SetState(true, true, true, true); // テキストメニューを最前面に移動する _textMenu->ToFront(); } } } } } return error; } // 色の定義 #define ATOM_MENU_ELEGANT_LIGHT {0x00, 0xCB, 0xBD, 0xDC} #define ATOM_MENU_ELEGANT_BASE {0x00, 0xAB, 0xA7, 0xC4} #define ATOM_MENU_ELEGANT_DARK {0x00, 0x00, 0x00, 0x00} #define ATOM_MENU_ELEGANT_TITLE_BACK {0x00, 0xBF, 0xE6, 0xCF} #define ATOM_MENU_ELEGANT_TITLE_FORE {0x00, 0xFF, 0xFF, 0xFF} #define ATOM_MENU_ELEGANT_ITEM_FORE {0x00, 0x00, 0x00, 0x00} #define ATOM_MENU_ELEGANT_ITEM_BACK {0x00, 0xAB, 0xA7, 0xC4} #define ATOM_MENU_ELEGANT_SELBACK {0x00, 0xFC, 0xCD, 0xE5} #define ATOM_MENU_ELEGANT_SELFORE {0x00, 0xFF, 0x00, 0x00} #define ATOM_MENU_CARNIVAL_LIGHT {0x00, 0xFF, 0xCC, 0x00} #define ATOM_MENU_CARNIVAL_BASE {0x00, 0xFF, 0x7F, 0x00} #define ATOM_MENU_CARNIVAL_DARK {0x00, 0x0A, 0x50, 0xA1} #define ATOM_MENU_CARNIVAL_TITLE_BACK {0x00, 0x7D, 0x01, 0x77} #define ATOM_MENU_CARNIVAL_TITLE_FORE {0x00, 0xFF, 0xFF, 0xFF} #define ATOM_MENU_CARNIVAL_ITEM_FORE {0x00, 0xFF, 0xFF, 0xFF} #define ATOM_MENU_CARNIVAL_ITEM_BACK {0x00, 0xFF, 0x7F, 0x00} #define ATOM_MENU_CARNIVAL_SELBACK {0x00, 0xFF, 0xFF, 0x00} #define ATOM_MENU_CARNIVAL_SELFORE {0x00, 0x09, 0x30, 0x73} #define ATOM_MENU_DYNAMIC_LIGHT {0x00, 0xFF, 0xCC, 0x00} #define ATOM_MENU_DYNAMIC_BASE {0x00, 0x80, 0x9C, 0xC9} #define ATOM_MENU_DYNAMIC_DARK {0x00, 0x0A, 0x50, 0xA1} #define ATOM_MENU_DYNAMIC_TITLE_BACK {0x00, 0xFF, 0xFF, 0x00} #define ATOM_MENU_DYNAMIC_TITLE_FORE {0x00, 0x00, 0x00, 0x00} #define ATOM_MENU_DYNAMIC_ITEM_FORE {0x00, 0x00, 0x00, 0x00} #define ATOM_MENU_DYNAMIC_ITEM_BACK {0x00, 0x80, 0x9C, 0xC9} #define ATOM_MENU_DYNAMIC_SELBACK {0x00, 0xFF, 0x00, 0x00} #define ATOM_MENU_DYNAMIC_SELFORE {0x00, 0xFF, 0xFF, 0xFF} #define ATOM_MENU_MONO_LIGHT {0x00, 0xFF, 0xFF, 0xFF} #define ATOM_MENU_MONO_BASE {0x00, 0x00, 0x00, 0x00} #define ATOM_MENU_MONO_DARK {0x00, 0x00, 0x00, 0x00} #define ATOM_MENU_MONO_TITLE_BACK {0x00, 0x7F, 0x7F, 0x7F} #define ATOM_MENU_MONO_TITLE_FORE {0x00, 0x00, 0x00, 0x00} #define ATOM_MENU_MONO_ITEM_FORE {0x00, 0xFF, 0xFF, 0xFF} #define ATOM_MENU_MONO_ITEM_BACK {0x00, 0x00, 0x00, 0x00} #define ATOM_MENU_MONO_SELBACK {0x00, 0x7F, 0x7F, 0x7F} #define ATOM_MENU_MONO_SELFORE {0x00, 0xFF, 0xFF, 0xFF} // テキストメニューの結果ハンドラの実装 XANDLER_IMPLEMENT_VOIDRESULT(helloworld, OnMenuResult, invoker, reason, result) { // テキストメニューの配色セット static UserColor::AtomRecConst color[] = { { ATOM_MENU_ELEGANT_LIGHT, ATOM_MENU_ELEGANT_BASE, ATOM_MENU_ELEGANT_DARK, ATOM_MENU_ELEGANT_TITLE_FORE, ATOM_MENU_ELEGANT_TITLE_BACK, ATOM_MENU_ELEGANT_ITEM_FORE, ATOM_MENU_ELEGANT_ITEM_BACK, ATOM_MENU_ELEGANT_SELFORE, ATOM_MENU_ELEGANT_SELBACK }, { ATOM_MENU_CARNIVAL_LIGHT, ATOM_MENU_CARNIVAL_BASE, ATOM_MENU_CARNIVAL_DARK, ATOM_MENU_CARNIVAL_TITLE_FORE, ATOM_MENU_CARNIVAL_TITLE_BACK, ATOM_MENU_CARNIVAL_ITEM_FORE, ATOM_MENU_CARNIVAL_ITEM_BACK, ATOM_MENU_CARNIVAL_SELFORE, ATOM_MENU_CARNIVAL_SELBACK }, { ATOM_MENU_DYNAMIC_LIGHT, ATOM_MENU_DYNAMIC_BASE, ATOM_MENU_DYNAMIC_DARK, ATOM_MENU_DYNAMIC_TITLE_FORE, ATOM_MENU_DYNAMIC_TITLE_BACK, ATOM_MENU_DYNAMIC_ITEM_FORE, ATOM_MENU_DYNAMIC_ITEM_BACK, ATOM_MENU_DYNAMIC_SELFORE, ATOM_MENU_DYNAMIC_SELBACK }, { ATOM_MENU_MONO_LIGHT, ATOM_MENU_MONO_BASE, ATOM_MENU_MONO_DARK, ATOM_MENU_MONO_TITLE_FORE, ATOM_MENU_MONO_TITLE_BACK, ATOM_MENU_MONO_ITEM_FORE, ATOM_MENU_MONO_ITEM_BACK, ATOM_MENU_MONO_SELFORE, ATOM_MENU_MONO_SELBACK } }; switch (reason) { case SFP16_RESULT_OK: // 項目が選択されたとき // 選択項目のテキストをデバッグウィンドウに表示する TRACE("'%S' is selected", _textMenu->GetItemText(static_cast<SInt16>(result)).GetCString()); switch (result) { case 0: case 1: case 2: case 3: // 項目のインデックスに応じてテキストメニューの配色を変える SetMenuColors(color[result]); break; case 5: // メニュースタイルをスクロールスタイルに変更する _textMenu->SetMenuStyle(SFZTextMenu::SCROLLABLE_STYLE); break; case 6: // メニュースタイルをページスタイルに変更する _textMenu->SetMenuStyle(SFZTextMenu::PAGE_STYLE); break; } break; case SFP16_RESULT_ESCAPE: // ESCAPE キー(デフォルトではクリアキー)が押されたとき // テキストメニューを閉じる invoker->Terminate(); break; } return; } // テキストメニューの色をまとめて設定する Void helloworld::SetMenuColors(UserColorConstRef color) { if (_textMenu != null) { // メニュータイトルの前景色を設定する _textMenu->SetTitleForeColor(color.titleFore); // メニュータイトルの背景色を設定する _textMenu->SetTitleBackColor(color.titleBack); // 選択項目の背景色を設定する _textMenu->SetSelBackColor(color.selBack); // 選択項目の前景色を設定する _textMenu->SetSelForeColor(color.selFore); // メニューのベベルカラーを設定する _textMenu->SetBevelColor(SFXBevelColor(color.light, color.base, color.dark)); // すべての項目の前景色と背景色を設定する for (SInt16 i = 0; i < _textMenu->GetItemCount(); ++i) { _textMenu->SetItemForeColor(i, color.itemFore); _textMenu->SetItemBackColor(i, color.itemBack); } } return; }
メニューの親レスポンダ | |
---|---|
メニューの親レスポンダはアプリケーションクラス[SFYApplication がデフォルトで保持するルート(SFZRoot)]にします。 ルートは、SFYApplication::GetThis 関数または SFYApplication::GetRoot 関数を呼び出して取得します。 |
テキストメニューの操作 | |
---|---|
テキストメニューは、選択キーによりメニューの選択項目を移動し、 操作キーまたはアクセスキーにより選択項目を操作します(実際に選択します)。 操作キーまたはアクセスキーを押下すると、 テキストメニューは結果イベントを受信します。 SFYResponder::RegisterHandler 関数を使用して、 結果イベントを受信する 結果ハンドラをテキストメニューに登録することが可能です。 デフォルトでは、↑/↓キーが選択キーに設定されています。 選択キーは、 SFYMenu::SetSelectUpKey / SFYMenu::SetSelectDownKey 関数により変更可能です。 デフォルトでは、セレクトキー(AVK_SELECT)が操作キーに設定されています。 操作キーは、 SFYMenu::SetOperateKey 関数により変更可能です。 アクセスキーとは、項目にキーを割り当て、 そのキーが押下されると、割り当てた項目を選択項目にし、かつ操作する(実際に選択する)機能です。 SFZTextMenu::SetItemAccessKey 関数を使用して設定します。 |
初期画面で 2 キーが押されると、 テキストメニューを表示するようにします。
例 3.48. 初期画面における描画処理とキー処理の変更
// helloworld アプリケーションクラスの描画ハンドラの実装 XANDLER_IMPLEMENT_VOIDRENDER(helloworld, OnRenderRequest, invoker, reason, graphics) { unused(invoker); // helloworld アプリケーションクラス(ルート)のローカル領域(携帯電話の画面)の背景は // SetBackgroundColor 関数で設定した色(デフォルト: 白色)で塗り潰される // *** 太字が修正部分 graphics->DrawSingleText("Key 1- Controls", SFXGrid(20, 20), GetLocalBound(), COLOR_BLACK); graphics->DrawSingleText("Key 2- TextMenu", SFXGrid(20, 40), GetLocalBound(), COLOR_BLACK); return; } // helloworld アプリケーションクラスのキーハンドラの実装 XANDLER_IMPLEMENT_BOOLEVENT(helloworld, OnKey, invoker, event) { unused(invoker); // *** 太字が追加部分 // アプリケーションクラスに可視状態の子レスポンダが存在しないときだけキー処理をする if (this->GetChildFront(true, false, false, false) == null) { switch (event.GetP16()) { case AVK_SELECT: Terminate(); return true; case AVK_1: TRACE("key 1"); if (MakeMy() != SFERR_NO_ERROR) { return false; } return true; case AVK_2: // 2 キーが押されたとき TRACE("key 2"); // メニューを作成する if (MakeMenu() != SFERR_NO_ERROR) { return false; } // キーイベントを処理したので true を返す return true; } } // キーイベントを処理しなかったときは false を返す return false; }
太字部分のコード
// ...(省略)... // アプリケーションクラスに可視状態の子レスポンダが存在しないときだけキー処理をする if (this->GetChildFront(true, false, false, false) == null) { // ...(省略)...
の追加により、helloworld アプリケーションクラス(ルート[SFZRoot])は、 可視状態が "ON" である子レスポンダを持つとき、 すなわち、ウィンドウ(MyWindow)またはテキストメニュー(_textMenu)が表示されているとき、 helloworld::OnKey キーハンドラはキーイベントを処理しません。
このコードがなければ、 ウィンドウ(MyWindow)またはテキストメニュー(_textMenu)で処理されなかったキーイベントは、 helloworld::OnKey キーハンドラで処理されてしまいます。
シミュレータでの実行結果は以下の通りです。
Copyright(c) 2002 - 2024 Sophia Cradle Incorporated All Rights Reserved. |