创建本地菜单
要创建一个菜单,先构造一个NativeMenu对象作为根菜单:
var root:NativeMenu = new NativeMenu();
作为窗体或应用程序的根菜单,所有的菜单项必须为子菜单(上下文菜单的根菜单可包含所有三种类型的菜单项),AIR提供了两种方法创建子菜单。你可以通过菜单的addSubmenu()方法添加菜单项:
var editMenu:NativeMenuItem = root.addSubmenu(new NativeMenu(), "Edit");
你也可以创建菜单项然后再赋值给子菜单:
var editMenu:NativeMenuItem = root.addItem("Edit");
editMenu.submenu = new NativeMenu();
菜单创建好后,再赋值给应用程序,窗体或上下文菜单:
Shell.shell.menu = root;
nativeWindowObject.menu = root;
interactiveObject.contextMenu = root;
DockIcon(Shell.shell.icon).menu = root;
SystemTrayIcon(Shell.shell.icon).menu = root;
定义菜单项,子菜单和分隔符
一个菜单项可以是一个命令项,一个子菜单或一个分隔符。一个菜单项如果设置构造函数的isSeparator参数为true这变成一个分隔符。一个菜单项如果赋值给NativeMenu对象的submenu属性则变成一个子菜单(或使用addSubmenu() 方法),否则菜单项就是一个命令项,只有命令项可以发出select事件。
菜单中的菜单项顺序就是其加入的先后顺序,除非你自己修改了其索引值,如通过addItemAt()方法在指定位置加入菜单项。
var copy:NativeMenuItem = new NativeMenuItem("Copy",false);
copy.addEventListener(Event.SELECT,onCopyCommand);
editMenu.addItem(copy);
var editMenu:NativeMenuItem = new NativeMenuItem("Edit", false);
editMenu.submenu = new NativeMenu();
也可以使用菜单的addSubmenu()方法添加菜单项:
var editMenu:NativeMenuItem = root.addSubmenu(new NativeMenu(), "Edit");
var separatorA:NativeMenuItem = new NativeMenuItem("A", true);
editMenu.addItem(separatorA);
创建一个上下文菜单
在AIR,ContextMenu API 类继承自NativeMenu类。ContextMenu提供了一个事件属性,ContextMenuEvent.mouseTarget,其确定打开该菜单的对象。
上下文菜单(Context menus)可赋值给任何继承自InteractiveObject 类的Flash对象。通过设置对象的contextMenu属性进行赋值。
上下文菜单仍可以包含命令项及分隔符,在AIR上下文菜单中没有默认的菜单项。
下面的例子创建了一个简单的edit 菜单:
var editContextMenu:ContextMenu = new ContextMenu();
var item:NativeMenuItem;
item = editContextMenu.addItem(new ContextMenuItem("Cut"));
item.name="Cut";
editContextMenu.addItem(new ContextMenuItem("Copy"));
item.name="Copy";
editContextMenu.addItem(new ContextMenuItem("Paste"));
item.name="Paste";
editContextMenu.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, function(event:ContextMenuEvent):void{
var command:NativeMenuItem = event.target as NativeMenuItem;
switch (command.name){
case "Cut" :
doCutCommand(event.mouseTarget);
break;
case "Copy" :
doCopyCommand(event.mouseTarget);
break;
case "Paste" :
doPasteCommand(event.mouseTarget);
break;
}
});
this.contextMenu = editContextMenu; //Where "this" is an InteractiveObject
显示弹出式菜单
通过调用菜单的display()方法可以随时在窗体的任意位置显示弹出式菜单。
下面的方法显示一个定义弹出式对象的菜单:
private function onMouseClick(event:MouseEvent):void{
popupMenu.display(event.target.stage, event.stageX, event.stageY);
}
注意:实际上没有必要在事件处理函数中显示菜单,任何方法都可以调用display()方法。
处理菜单事件
当一个菜单项被点击时,事件就会被触发,AIR程序会对此作出反应。
下面的代码输出被激活的菜单名称:
var submenu:NativeMenu = new NativeMenu();
var red:NativeMenuItem = new NativeMenuItem("Red");
red.addEventListener(Event.SELECT,announceSelection)
var green:NativeMenuItem = new NativeMenuItem("Green");
green.addEventListener(Event.SELECT,announceSelection)
var blue:NativeMenuItem = new NativeMenuItem("Blue");
blue.addEventListener(Event.SELECT,announceSelection)
var menuItem:NativeMenuItem = new NativeMenuItem("Change Color");
submenu.addItem(red);
submenu.addItem(green);
submenu.addItem(blue);
menuItem.submenu = submenu;
Shell.shell.menu.addItem(menuItem);
function announceSelection(e:Event):void {
var menuItem:NativeMenuItem = e.target as NativeMenuItem;
trace(menuItem.label + " has been selected")
}
声明式定义菜单
输入菜单和菜单项的属性是一件很枯燥的事情,不过菜单是一个有规律的层级结构,可以使用XML格式定义直接写在函数里。
下面的类继承自NativeMenu,在构造函数里传入XML对象,像这样:
{
import flash.display.NativeMenu;
import flash.display.NativeMenuItem;
import flash.events.Event;
public class DeclarativeMenu extends NativeMenu
{
public function DeclarativeMenu(XMLMenuDefinition:XML):void{
super();
addChildrenToMenu(this, XMLMenuDefinition.children());
}
private function addChildrenToMenu(menu:NativeMenu,
children:XMLList):NativeMenuItem{
var menuItem:NativeMenuItem;
var submenu:NativeMenu;
for each (var child:XML in children){
if(String(child.@label).length > 0){
menuItem = new NativeMenuItem(child.@label);
menuItem.name = child.name();
} else {
menuItem = new NativeMenuItem(child.name());
menuItem.name = child.name();
}
menu.addItem(menuItem);
if(child.children().length() > 0){
menuItem.submenu = new NativeMenu();
addChildrenToMenu(menuItem.submenu,child.children());
}
}
return menuItem;
}
}//End class
} // End package
要使用这个类创建菜单,只需要传入一个XML格式的菜单定义即可:
var menuDefinition:String =
"<root>" +
"<FileMenu label='File'>" +
"<NewMenu label='New'>" +
"<NewTextFile label='Text file'/>" +
"<NewFolder label='Folder'/>" +
"<NewProject label='Project'/>" +
"</NewMenu>" +
"<OpenCommand label='Open'/>" +
"<SaveCommand label='Save'/>" +
"</FileMenu>" +
"<EditMenu label='Edit'/>" +
"<CutCommand label='Cut'/>" +
"<CopyCommand label='Copy'/>" +
"<PasteCommand label='Paste'/>" +
"<EditMenu/>" +
"<FoodItems label='Food Items'>" +
"<Jellyfish/>" +
"<Tripe/>" +
"<Gizzard/>" +
"</FoodItems>" +
"</root>";
var test:DeclarativeMenu = new DeclarativeMenu(new XML(menuDefinition));
要监听菜单事件,你可以直接监听根菜单即可,通过event.target.name属性判定哪个命令项被触发,你也可以根据菜单名称搜索菜单项并添加独立的事件监听器。
例子:窗体和应用程序菜单
下面的例子使用菜单结构创建菜单,该例子也演示了事件处理过程:
import flash.display.NativeMenu;
import flash.display.NativeMenuItem;
import flash.display.NativeWindow;
import flash.display.Sprite;
import flash.events.Event;
import flash.filesystem.File;
import flash.system.Shell;
public class MenuExample extends Sprite
{
private var recentDocuments:Array = new Array(new File("c:/GreatGatsby.pdf"),
new File("c:/WarAndPeace.pdf"),
new File("c:/Iliad.pdf"));
public function MenuExample()
{
var fileMenu:NativeMenuItem;
var editMenu:NativeMenuItem;
if(NativeWindow.supportsMenu){
stage.nativeWindow.menu = new NativeMenu();
stage.nativeWindow.menu.addEventListener(Event.SELECT, selectCommandMenu);
fileMenu = stage.nativeWindow.menu.addItem(new NativeMenuItem("File"));
fileMenu.submenu = createFileMenu();
editMenu = stage.nativeWindow.menu.addItem(new NativeMenuItem("Edit"));
editMenu.submenu = createEditMenu();
}
if(Shell.supportsMenu){
Shell.shell.menu.addEventListener(Event.SELECT, selectCommandMenu);
fileMenu = Shell.shell.menu.addItem(new NativeMenuItem("File"));
fileMenu.submenu = createFileMenu();
editMenu = Shell.shell.menu.addItem(new NativeMenuItem("Edit"));
editMenu.submenu = createEditMenu();
}
}
public function createFileMenu():NativeMenu{
var fileMenu:NativeMenu = new NativeMenu();
fileMenu.addEventListener(Event.SELECT,selectCommandMenu);
var newCommand:NativeMenuItem = fileMenu.addItem(new NativeMenuItem("New"));
newCommand.addEventListener(Event.SELECT,selectCommand);
var saveCommand:NativeMenuItem = fileMenu.addItem(new NativeMenuItem("Save"));
saveCommand.addEventListener(Event.SELECT,selectCommand);
var openRecentMenu:NativeMenuItem =
fileMenu.addItem(new NativeMenuItem("Open Recent"));
openRecentMenu.submenu = new NativeMenu();
openRecentMenu.submenu.addEventListener(Event.DISPLAYING,
updateRecentDocumentMenu);
openRecentMenu.submenu.addEventListener(Event.SELECT,selectCommandMenu);
return fileMenu;
}
public function createEditMenu():NativeMenu{
var editMenu:NativeMenu = new NativeMenu();
editMenu.addEventListener(Event.SELECT,selectCommandMenu);
var copyCommand:NativeMenuItem = editMenu.addItem(new NativeMenuItem("Copy"));
copyCommand.addEventListener(Event.SELECT,selectCommand);
var pasteCommand:NativeMenuItem =
editMenu.addItem(new NativeMenuItem("Paste"));
pasteCommand.addEventListener(Event.SELECT,selectCommand);
editMenu.addItem(new NativeMenuItem("",true));
var preferencesCommand:NativeMenuItem =
editMenu.addItem(new NativeMenuItem("Preferences"));
preferencesCommand.addEventListener(Event.SELECT,selectCommand);
return editMenu;
}
private function updateRecentDocumentMenu(event:Event):void{
trace("Updating recent document menu.");
var docMenu:NativeMenu = NativeMenu(event.target);
for each(var item:NativeMenuItem in docMenu.items){
docMenu.removeItem(item);
}
for each(var file:File in recentDocuments){
var menuItem:NativeMenuItem =
docMenu.addItem(new NativeMenuItem(file.name));
menuItem.data = file;
menuItem.addEventListener(Event.SELECT, selectRecentDocument);
}
}
private function selectRecentDocument(event:Event):void{
trace("Selected recent document: " + event.target.data.name);
}
private function selectCommand(event:Event):void{
trace("Selected command: " + event.target.label);
}
private function selectCommandMenu(event:Event):void{
if(event.currentTarget.parent){
var menuItem:NativeMenuItem =
findItemForMenu(NativeMenu(event.currentTarget));
if(menuItem){
trace("Select event for "" +
event.target.label +
"" command handled by menu: " +
menuItem.label);
}
} else {
trace("Select event for "" +
event.target.label +
"" command handled by root menu.");
}
}
private function findItemForMenu(menu:NativeMenu):NativeMenuItem{
for each(var item:NativeMenuItem in menu.parent.items){
if(item){
if(item.submenu == menu){
return item;
}
}
}
return null;
}
}
}