こんなようなもの。
flash.ui.ContextMenu - ActionScript 3.0 言語およびコンポーネントリファレンス なるものを使用する。使い方はこんな感じ。といってもリファレンスの例ほぼそのままだけど。
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" applicationComplete="init()"> <mx:Script> <![CDATA[ private function init():void { var rmenu:ContextMenu; var rmenuitem:ContextMenuItem; rmenu = new ContextMenu(); rmenu.hideBuiltInItems(); rmenuitem = new ContextMenuItem("hoge 1"); rmenu.customItems.push(rmenuitem); rmenuitem = new ContextMenuItem("separator 2",true); rmenu.customItems.push(rmenuitem); for (var i:int=3; i<40; i++){ rmenuitem = new ContextMenuItem("hoge" + i); rmenu.customItems.push(rmenuitem); } this.contextMenu = rmenu; } ]]> </mx:Script> </mx:Application>
ContextMenu#hideBuiltInItems() で拡大だとかプリントだとかのビルトインコンテキストメニューが消せる。ただし、設定と Adobe Flash Player x については消せない。また、メニューアイテムは最大 15 個までという制限がある。↑のソースだとタクサン入れてますが見事にスルーされる。サブメニューも作れないようだ。あと、ContextMenuItem のコンストラクタの第二引数を true にすると、その ContextMenuItem の上部にセパレータを表示する。
mx.controls.Menu と使い勝手余りにも違うんでなんじゃこりゃーと思ったけど、コンテキストメニューは特殊扱いみたいだねぇ。ContextMenu のリファレンス見ると Adobe AIR でしか使えない API がいっぱいあるし、ドキュメントにも「ただし AIR では」って記述がたくさんある。AIR だと 15 個制限もないし、サブメニューも作れるし、設定とバージョン情報のメニューもないし、メニューアイテムに flash.display.NativeMenuItem ってのが使えたり、と色々違う。
Flex と AIR では出来ることが違うの当たり前ってのはわかってたけど、細かいとこが結構違うんだなぁ……
気を取り直して続き。コンテキストメニューを表示する場所は、Application 単位だけじゃなくてコンポーネント単位に設定できる。とりあえずこんな感じにすると、swf の領域全体、ボタン1、ボタン2それぞれに異なるコンテキストメニューが表示できる。
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" applicationComplete="init()"> <mx:Script> <![CDATA[ import mx.core.UIComponent; private function init():void { initComponentContextMenu(this, "hoge"); initComponentContextMenu(button1, "button1"); initComponentContextMenu(button2, "button2"); } private function initComponentContextMenu(component:UIComponent, label:String):void { var rmenu:ContextMenu = new ContextMenu(); var rmenuitem:ContextMenuItem = new ContextMenuItem(label); rmenuitem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, function():void{trace(label);}); rmenu.hideBuiltInItems(); rmenu.customItems.push(rmenuitem); component.contextMenu = rmenu; } ]]> </mx:Script> <mx:Button id="button1" label="ボタン1"/> <mx:Button id="button2" label="ボタン2"/> </mx:Application>
メニューアイテムが ContextMenuItem クラスとして独立してるおかげか、イベントリスナーが ContextMenuItem 単位に設定できるのも Menu との違いかねぇ。
次に、15 個制限の壁を突破するか右クリックメニューを消滅させる方法について調べてみた。とりあえず 右クリックメニューを出さない方法はありますか? - フォーラム - Flex User Group がひっかかった。そこに Custom Right-click in Flash | polyGeek.com という URL が紹介されていた。これによると、ExternalInterface を使用して javascript で右クリックのイベントを補足し、ActionScript のメソッドを呼ぶ、ということをやっている。ややこしいなー。
で、これを試してみようと思ったら ExternalInterface の動かし方がよくわからず、しばらく唸っていた。まず最初の原因はコイツ。
IEで戻り値がnullの件、allowScriptAccessはalwaysにしたのに、FFでは正常なのにと...
SWF貼り付けのobjectタグのID名に "external"を入れると動作する。
external、だけじゃだめで、*external or external* or *external* ってこと(*は任意の文字列)
わかんないってそんなの……w
今はとりあえず IE でだけ動作確認してるんだけど 【解決!】ExternalInterfaceにハマる (Nega Diary) とか見ると色々イヤな予感が。こういうのがあるから Web のフロントエンド部分の開発はイヤらしいんだよなぁw
ここで疲れたので ExternalInterface 使って右クリック操作するのを試すのは止めてしまった。