ApplicationCommandManager 3-3

与ApplicationCommandManager命令管理器和ApplicationCommandTarget命令目标关系异常紧密且非常重要的是ApplicationCommandInfo命令信息结构体,其代表每一条命令的详细信息,命令目标类的getCommandInfo()函数的执行结果,即将有关数据保存到该结构体中。其枚举、成员函数和数据成员均为public类型的。

ApplicationCommandInfo的枚举
 isDisabled 无法执行此命令,即该命令处于禁用(灰显)状态
 isTicked 该命令已经选择
 wantsKeyUpDownCallbacks KeyPressMappingSet将两次触发该命令
 hiddenFromKeyEditor 快捷键编辑对话框中不显示此命令
 readOnlyInKeyEditor 快捷键编辑对话框中显示此命令, 但不允许修改其快捷键
 dontTriggerVisualFeedback 快捷键触发命令时, 该命令所关联的按钮或菜单不闪烁

ApplicationCommandInfo的成员函数:
 setInfo () 设置此命令的详细信息
 setActive () 设置此命令是否可用
 setTicked () 设置此命令是否已选
 addDefaultKeypress () 触发此命令的快捷键,每条命令均可设置多组快捷键

ApplicationCommandInfo的数据成员:
 commandID 命令的唯一编号,数据类型为CommandID,解释见后
 shortName 命令的简略描述(菜单项和按钮的文本)
 description 命令的详细描述
 categoryName 此命令所属的类别的名称
 defaultKeypresses 触发此命令的0个或多个快捷键,KeyPress数组
 flags 本类枚举常量的位或结果

ApplicationCommandInfo的数据成员commandID的类型为CommandID,该数据类型其实是int的typedef,位于名字空间StandardApplicationCommandIDs中,该名字空间中预定义了一批static const类型的CommandID数据,每个代表一条JUCE类库预定义的命令ID,注意:是命令ID,而非命令。编程时,可直接使用这些预定义的命令ID:
 StandardApplicationCommandIDs::quit “退出”命令的ID.
 StandardApplicationCommandIDs::del “删除”命令的ID.
 StandardApplicationCommandIDs::cut “剪切”命令的ID.
 StandardApplicationCommandIDs::copy “复制到剪贴板”命令的ID.
 StandardApplicationCommandIDs::paste “粘贴剪贴板内容”命令的ID.
 StandardApplicationCommandIDs::selectAll “全部选择”命令的ID.
 StandardApplicationCommandIDs::deselectAll “全部不选”命令的ID.
 StandardApplicationCommandIDs::undo “撤销” 命令的ID.
 StandardApplicationCommandIDs::redo “重做” 命令的ID.

命令目标类在实现getCommandInfo()函数时,该函数的1参即为指定命令ID,可直接在switch结构体中给出以上预定义的命令ID:

// JUCE预置的命令ID,此处定义该ID的命令信息
case StandardApplicationCommandIDs::undo: 
     result.setInfo (L"撤销", L"撤销操作.", CommandCategories::editing, 0);
     result.setActive (isSomethingSelected());
     result.addDefaultKeypress ('z', ModifierKeys::commandModifier);
     break;

弹出式菜单添加菜单项时,这么写即可:

/* 添加退出菜单项。该命令ID所执行的具体功能,已在JUCEApplication中做了定义,因此无需在命令目标类的perform()中重复定义此ID所执行的代码 */
menu.addCommandItem (commandManager, StandardApplicationCommandIDs::quit); 

实际编程中,本程序所需的所有命令ID,可以以枚举的方式在每个程序命令目标类中进行定义,但这种做法仅适合于小型程序。如果程序较大,最好集中设置所有的程序命令ID,将其写在一个h头文件中,用命名空间包裹起来,每个命令ID均为static const int类型。要使用命令ID的类,#include该头文件,而后在语句中直接用“名称空间::名称”的形式来调用。程序命令的类别,也可定义在此头文件中。示例:

/** 本程序所用到的所有命令的ID集中定义于此. 为避免和JUCE内置的命令索引冲突,从0x20000开始*/
namespace CommandIDs
{
    static const int open   = 0x20000;
    static const int close  = 0x20001;
    static const int save   = 0x20002;
    //...
}

 /** 本程序所用到的所有命令的类别,同样集中定义于此. */
namespace CommandCategories
{
    static const wchar_t* const general  = L"常规";
    static const wchar_t* const editing  = L"编辑";
    static const wchar_t* const view     = L"视图";
}

使用程序命令的代码中,比如添加菜单项时,这么写即可:

menu.addCommandItem (commandManager, CommandIDs::open);

与命令管理器的嵌套类命令信息相对应,命令目标类也有一个嵌套类(结构体):InvocationInfo。命令目标类的perform()函数的参数即为该结构体对象。其public枚举:
 direct 命令由代码直接调用
 fromKeyPress 命令由快捷键调用
 fromMenu 命令由菜单调用
 fromButton 命令由点击按钮来调用

InvocationInfo的public数据成员:
 commandID 此命令的ID
 commandFlags 命令的标识,对应ApplicationCommandInfo的枚举
 invocationMethod 触发此命令的事件类型,返回值为本结构体的枚举
 originatingComponent 触发此命令时拥有键盘焦点的组件
 keyPress 此命令的快捷键
 isKeyDown 如果命令由键按下所调用,则为true。键已释放,则为false
 millisecsSinceKeyPressed 如果键已释放,此属性为键释放前按下了多长时间(毫秒)

最后给出实现程序命令功能最重要的核心类ApplicationCommandManager的静态函数与成员函数:(略)

小技巧

程序启动后,默认具有键盘焦点的组件为主窗口(DocumentWindow)。如果主窗口类不是命令目标,则按下的快捷键将无法被执行。可在主窗口类的构造函数中添加如下语句:

setWantsKeyboardFocus (false);   // 本类无需键盘焦点

// 捕获本组件内接收到的键盘事件。捕获器为命令管理器所持有的KeyPressMappingSet
addKeyListener (commandManager->getKeyMappings());