Palm Programmer's Laboratory
Palm OS Programmer's Companion Volume I/4-6
4-6 メニュー
メニューバーはメニューアイコンをタップすると表示されます。Palm OS 3.5 以降では、メニューバーはフォームのタイトルバーをタップしても表示されます。メニューバーはメニュータイトルの横並びのリストで、スクリーンの最上部に、アプリケーションウィンドウの上に重なるようにして表示されます。メニュータイトルをタップするとタイトルがハイライト表示され、その下にメニューが「プルダウン」されます( 図 4.16 参照 )。
図 4.16 メニュー
ユーザー操作により、メニューには以下の効果があります。
ユーザー操作 | 結果 |
---|---|
ペンでメニュー上をドラッグ | ペンの下にあるコマンドがハイライト表示。 |
メニュー上でペンを離す | そのメニューが選択され、メニューバーとメニューは非表示になる。 |
メニューバーとメニューの外側でペンを離す | メニューバーとメニューは非表示になり、なにも選択されない。 |
メニュータイトル内でペンを離す( Palm OS 3.5 以降のみ ) | メニューが選択されるまでメニューバーとメニューは表示されたまま。 |
メニューとメニューバーの外側でタップ | メニューバーとメニューは非表示になる。 |
メニューには以下の機能があります。
- セパレータ。これはメニューアイテムをグループ化するための線です。
- メニューアイテム内で右揃えで表示されるメニューショートカット。
- 最後に選択されたメニューの記憶。メニューが表示される際、最後に選択されたメニューがハイライト表示されます.
- メニューとメニューバーによって隠される背後の画像はメニュールーチンによって保存・復元されます。
- メニューが表示される際、カーソル(挿入ポイント)は非表示になります。
メニューのイベントは MenuHandleEvent によって処理されます。表 4.14 に、ユーザー操作がどのようにイベントに変換され、MenuHandleEvent がどのような応答をするのかを示します。
表 4.14 メニューのイベントフロー
ユーザー操作 | 生成イベント | MenuHandleEvent の応答 |
---|---|---|
メニューバーをペンで操作 | メニューウィンドウを識別する winEnterEvent | ペンを追跡 |
メニューアイテムを選択する | x および y 座標を指定した penUpEvent | 選択アイテムの ID を指定した menuEvent をイベントキューに追加 |
メニューの可視性チェック
オペレーティングシステムがメニューを描画する際、メニューウィンドウがアクティブな描画ウィンドウになります。オペレーティングシステムはそれ以前のアクティブ描画ウィンドウに対して winExitEvent を発行し、メニューウィンドウに対して winEnterEvent を発行します。メニューが消されると、システムはメニューウィンドウに対して winExitEvent を発行し、メニューが描画される前にアクティブだったウィンドウに対して winEnterEvent を発行します。
ウィンドウに対してカスタム描画を行なうアプリケーションでは、メニューが表示されているかどうかをチェックしたいと思うものです。そのようなアプリケーションでは、メニューの上に描画してしまっていないことを確認したいのです。お勧めの方法は、描画ウィンドウに対する winExitEvent を受け取ったら描画をやめ、対応する winEnterEvent を受け取ったら描画を再開することです。例えば、以下のコードは Reptoids サンプルアプリケーションのメインイベントループから抜粋したものです。
EvtGetEvent (&event, TimeUntillNextPeriod()); if (event.eType == winExitEvent) { if (event.data.winExit.exitWindow == (WinHandle)FrmGetFormPtr(MainView)) { // stop drawing. } } else if (event.eType == winEnterEvent) { if (event.data.winEnter.enterWindow == (WinHandle)FrmGetFormPtr(MainView) && event.data.winEnter.enterWindow == (WinHandle)FrmGetFirstForm ()) { // start drawing } }
このテクニックがメニューに固有のものではないことに注意してください。アプリケーションは描画ウィンドウが他のウィンドウによって隠された場合、描画をやめなければなりません。winEnterEvent と winExitEvent をチェックする方法ならば、それができていることになります。
ダイナミックメニュー
バージョン 3.5 未満の Palm OS では、メニューは( Constructor や他のツールで作成される )メニューリソースからロードされるもので、プログラムで変更することはできませんでした。Palm OS 3.5 以降では、メニューリソースがロードされる際にメニューアイテムを追加したり、表示/非表示を切り替えたりすることができます。
メニューリソースがロードされると、menuOpenEvent が発行されます。( このイベントがバージョン 3.5 以降のみであることに注意してください。それよりも前のリリースでは使われません。)このイベントに対する応答で、MenuAddItem をコールしてプルダウンメニューにメニューアイテムを追加したり、MenuHideItem でメニューアイテムを非表示にしたり、MenuShowItem でメニューアイテムを表示したりできます。
アプリケーションセッションにおいて、menuOpenEvent を何度か受信する場合があるかもしれません。メニューリソースは、それがアクティブメニューになるたびにロードされます。メニューが初めてアクティブになるのはメニューを表示するようリクエストした場合か、フォームでコマンドキーストロークを入力した場合です。メニューは、それが関連付けれたフォームがアクティブな限りアクティブであり続けます。メニューは以下の条件によってアクティブでなくなります。
- FrmSetMenu がコールされてフォームのアクティブメニューが変更された場合
- モーダルフォームやアラートを含む新しいフォームがアクティブになった場合
アプリケーションのオプションメニューから About 項目を選択し、次に OK ボタンをタップしてメインフォームに戻る動作を考えます。About ダイアログが表示されると、それがアクティブフォームになり、メインフォームのメニューの状態がクリアされます。このメニューの状態はメインフォームが再びアクティブになった際にも復元されません。次にメニューがリクエストされた時、メニューリソースは再度ロードされ、新しい menuOpenEvent がキューに追加されます。
メニューを変更するのは、フォームがアクティブになってメニューがロードされた時だけにすべきです。ユーザーの状況によってメニューを追加したり表示/非表示を変更したりするべきではありません。Palm OS のユーザーインターフェースガイドラインではそのような挙動をしないように推奨しています。
メニューショートカット
メニューコマンドを選択する別のユーザーインターフェースとして、メニューショートカットを入力する方法があります。これは全てのバージョンの Palm OS でサポートされていますが、Palm OS 3.5 以降で拡張されています。
全てのバージョンの Palm OS では、Graffiti または Graffiti 2 のコマンドキーストロークに続けて文字を入力できます。入力した文字がアクティブメニュー内のメニューアイテムのショートカットの1つにマッチすれば、そのメニューアイテムの menuEvent が発行されます。この機能をサポートするために必要なのは、メニューアイテムリソースを作成する際にショートカット文字を指定することだけです。Palm OS のデフォルトの機能でショートカットを適切に処理してくれます。
- NOTE
- Graffiti 2 フィーチャセットが存在する場合、最初のストロークが( "l" や空白文字などの )別の文字にマッチするようなマルチストローク文字をキーボードショートカットに使うのは避けて下さい。
Palm OS 3.5 以降では、コマンドストロークを入力するとコマンドツールバー( 図 4.17 参照 )が表示されます。このツールバーはスクリーンと同じ幅を持ちます( それ以前のバージョンの Palm OS では、画面の左下に“Command:”という文字列が表示されていました )。コマンドツールバーは左側にステータスメッセージが表示され、右側にボタンが表示されます。コマンドストロークを入力した後、コマンドツールバー上で文字を入力するかボタンをタップするかします。どちらのアクションでもステータスメッセージが短時間表示され、(ほとんどの場合は)menuEvent がイベントキューに追加されます。
図 4.17 コマンドツールバー
ツールバーに表示されるボタンはユーザーコンテキストに依存します。編集可能なフィールドにフォーカスがある場合、フィールドマネージャはカット、コピー、ペーストのためのボタンをコマンドツールバーに表示します。アンドゥ可能なアクションがある場合、フィールドマネージャはアンドゥのためのボタンも表示します。
アクティブなアプリケーションはコマンドツールバーに独自のボタンを追加することもできます。そのためには、menuCmdBarOpenEvent に応答し、MenuCmdBarAddButton をコールしてボタンを追加します。リスト 4.1 にメモ帳アプリケーションのコードを示します。このコードでは、コマンドツールバーにセキュリティダイアログを表示するためのボタンを追加し、フィールドマネージャによる他のボタンの追加を抑止しています。
リスト 4.1 menuCmdBarOpenEvent への応答
else if (event->eType == menuCmdBarOpenEvent) { MenuCmdBarAddButton(menuCmdBarOnLeft, BarSecureBitmap, menuCmdBarResultMenuItem, ListOptionsSecurityCmd, 0); // Tell the field package to not add buttons // automatically; we've done it all ourselves. event->data.menuCmdBarOpen.preventFieldButtons = true; // Don't set handled to true; this event must // fall through to the system. }
システムには、ビームや削除などのコマンドを表現するビットマップが用意されています。アプリケーションがこれらのアクションを実行するのであれば、システムのビットマップを使用するべきです。表 4.15 にシステムビットマップとそれらが表現するコマンドの一覧を示します。これらを使用する場合、以下に示す順番で右から左に向かって使用するべきです。つまり、BarDeleteBitmap がこれらのビットマップの一番右に配置され、BarInfoBitmap は一番左に配置されます。
表 4.15 システムのコマンドツールバービットマップ
ビットマップ | コマンド |
---|---|
BarDeleteBitmap | レコードの削除 |
BarPasteBitmap | クリップボードの内容をカーソル位置に貼り付け |
BarCopyBitmap | 選択領域をコピー |
BarCutBitmap | 選択領域を切り取り |
BarUndoBitmap | 直前のアクションを元に戻す |
BarSecureBitmap | セキュリティダイアログを表示 |
BarBeamBitmap | 現在のレコードをビーム |
BarInfoBitmap | Info ダイアログを表示(ランチャー) |
コマンドツールバーに表示するボタンは 4 個か 5 個に制限すべきです。ボタンの数を制限するのには、2つの理由があります。まず、アクションが実行される前に表示されるステータスメッセージのためのスペースを空けて置く必要があります。ツールバーは短時間しか表示されないことを考慮する必要があります。ツールバー上のそれぞれのボタンの意味は即座に理解できなければなりません。多くのボタンがありすぎると、必要なボタンを見つけることができなくなってしまいます。
フィールドマネージャだけでも4つのボタンを表示する可能性があることに注意してください。フィールドにフォーカスがある場合でもこれを抑止して独自のボタンを表示したい場合は、リスト 4.1 に示したように menuCmdBarOpenEvent の preventFieldButtons フラグに true をセットします。