处理 MenuBuilder 菜单事件

Adobe AIR 1.0 和更高版本

与 NativeMenu 的用户交互是事件驱动的。当用户选择菜单项或打开菜单或子菜单时,NativeMenuItem 对象将调度一个事件。使用通过 MenuBuilder 框架创建的 NativeMenu 对象,可以将事件侦听器注册到各个 NativeMenuItem 对象或 NativeMenu。订阅和响应这些事件时,就好像您已经以手动方式而不是使用 MenuBuilder 框架创建了 NativeMenu 和 NativeMenuItem 对象。有关详细信息,请参阅 菜单的事件

MenuBuilder 框架补充了标准事件处理过程,从而使您可以在菜单数据源中为菜单项指定 select 事件处理函数。如果在菜单项数据源中指定 onSelect 字段,则当用户选择菜单项时,将调用所指定的函数。例如,假设以下 XML 节点包含在使用 MenuBuilder 框架加载的数据源中。当选择菜单项时,将调用名为 doSave() 的函数:

<menuitem label="Save" onSelect="doSave"/>

用于 XML 数据源时, onSelect 字段是 String。使用 JSON 数组时,此字段可以是有函数名称的 String。此外,仅对 JSON 数组,该字段还可以是对作为对象的函数的变量引用。但是,如果 JSON 数组使用 Function 变量引用,则必须在发生 onload 事件处理函数或 JavaScript 安全违规之前或在此期间创建菜单。在所有情况中,必须在全局作用域内定义所指定的函数。

调用所指定的函数时,运行时会向它传递两个参数。第一个参数是由 select 事件调度的事件对象。它是 Event 类的实例。传递给此函数的第二个参数是匿名对象,其中包含用于创建菜单项的数据。此对象有以下属性。每个属性的值均与原始数据结构中的值匹配,如果未在原始数据结构中设置该属性,则其值为 null

  • altKey

  • cmdKey

  • ctrlKey

  • defaultKeyEquivalentModifiers

  • enabled

  • keyEquivalent

  • label

  • mnemonicIndex

  • onSelect

  • shiftKey

  • toggled

  • type

以下示例用于实验 NativeMenu 事件。该示例包括两个菜单。窗口和应用程序菜单使用 XML 数据源创建。由 <ul> <li> 元素所表示的项目列表的上下文菜单使用 JSON 数组数据源创建。当用户选择菜单项时,屏幕上的文本区域将显示有关每个事件的信息。

以下代码是应用程序的源代码:

<html> 
    <head> 
        <title>Menu event handling example</title> 
        <script type="text/javascript" src="AIRAliases.js"></script> 
        <script type="text/javascript" src="AIRMenuBuilder.js"></script> 
        <script type="text/javascript" src="printObject.js"></script> 
        <script type="text/javascript"> 
            function fileMenuCommand(event, data) { 
                print("fileMenuCommand", event, data); 
            } 
             
            function editMenuCommand(event, data) { 
                print("editMenuCommand", event, data); 
            } 
             
            function moveItemUp(event, data) { 
                print("moveItemUp", event, data); 
            } 
             
            function moveItemDown(event, data) { 
                print("moveItemDown", event, data); 
            } 
             
            function print(command, event, data) { 
                var result = ""; 
                result += "<h1>Command: " + command + '</h1>'; 
                result += "<p>" + printObject(event) + "</p>"; 
                result += "<p>Data:</p>"; 
                result += "<ul>"; 
                for (var s in data) { 
                    result += "<li>" + s + ": " + printObject(data[s]) + "</li>"; 
                } 
                result += "</ul>"; 
                 
                var o = document.getElementById("output"); 
                o.innerHTML = result; 
            } 
        </script> 
        <style type="text/css"> 
            #contextList { 
                position: absolute; left: 0; top: 25px; bottom: 0; width: 100px; 
                background: #eeeeee; 
            } 
            #output { 
                position: absolute; left: 125px; top: 25px; right: 0; bottom: 0; 
            } 
        </style> 
    </head> 
    <body> 
        <div id="contextList"> 
            <ul> 
                <li>List item 1</li> 
                <li>List item 2</li> 
                <li>List item 3</li> 
            </ul> 
        </div> 
        <div id="output"> 
            Choose menu commands. Information about the events displays here. 
        </div> 
        <script type="text/javascript"> 
            var mainMenu = air.ui.Menu.createFromXML("mainMenu.xml"); 
            air.ui.Menu.setAsMenu(mainMenu); 
             
            var listContextMenu = air.ui.Menu.createFromJSON("listContextMenu.js"); 
            air.ui.Menu.setAsContextMenu(listContextMenu, "contextList") 
             
            // clear the default context menu 
            air.ui.Menu.setAsContextMenu(null); 
        </script> 
    </body>| 
</html>

以下代码是主菜单(“mainMenu.xml”)的数据源:

<?xml version="1.0" encoding="utf-8" ?> 
<root> 
    <menuitem label="File"> 
        <menuitem label="New" keyEquivalent="n" onSelect="fileMenuCommand"/> 
        <menuitem label="Open" keyEquivalent="o" onSelect="fileMenuCommand"/> 
        <menuitem label="Save" keyEquivalent="s" onSelect="fileMenuCommand"/> 
        <menuitem label="Save As..." keyEquivalent="S" onSelect="fileMenuCommand"/> 
        <menuitem label="Close" keyEquivalent="w" onSelect="fileMenuCommand"/> 
    </menuitem> 
    <menuitem label="Edit"> 
        <menuitem label="Cut" keyEquivalent="x" onSelect="editMenuCommand"/> 
        <menuitem label="Copy" keyEquivalent="c" onSelect="editMenuCommand"/> 
        <menuitem label="Paste" keyEquivalent="v" onSelect="editMenuCommand"/> 
    </menuitem> 
</root>

以下代码是上下文菜单(“listContextMenu.js”)的数据源;

[ 
    {label: "Move Item Up", onSelect: "moveItemUp"}, 
    {label: "Move Item Down", onSelect: "moveItemDown"} 
]

以下代码包含 printObject.js 文件中的代码。在本例中,该文件包括 printObject() 函数,该函数由应用程序使用,但它不影响菜单的操作。

function printObject(obj) { 
    if (!obj) { 
        if (typeof obj == "undefined") { return "[undefined]"; }; 
        if (typeof obj == "object") { return "[null]"; }; 
        return "[false]"; 
    } else { 
        if (typeof obj == "boolean") { return "[true]"; }; 
        if (typeof obj == "object") { 
            if (typeof obj.length == "number") { 
                var ret = []; 
                for (var i=0; i<obj.length; i++) { 
                    ret.push(printObject(obj[i])); 
                } 
                return ["[", ret.join(", "), "]"].join(" "); 
            } else { 
                var ret = []; 
                var hadChildren = false; 
                for (var k in obj) { 
                    hadChildren = true; 
                    ret.push ([k, " => ", printObject(obj[k])]); 
                } 
                if (hadChildren) { 
                    return ["{\n", ret.join(",\n"), "\n}"].join(""); 
                } 
            } 
        } 
        if (typeof obj == "function") { return "[Function]"; } 
        return String(obj); 
    } 
}