截取上下文菜单
在对象上单击鼠标右键时,将显示上下文菜单。通常,上下文菜单提供了用于处理选定对象的上下文相关功能,例如剪切、复制和粘贴。开发者可以在上下文菜单显示之前将其截获,以取消上下文菜单的执行,也可以通过替换上下文菜单条目或整个子菜单来加入、删除以及更改菜单。可以提供新的自定义上下文菜单。
上下文菜单的截取由查看器模式实现。此模式定义了对象之间一对多的关系,这样,当一个对象更改状态时,将通知其所有相关的对象。此实现支持多个截取程序。用于截取上下文菜单的根访问点是一个 com.sun.star.frame.Controller 对象。控制器实现 com.sun.star.ui.XContextMenuInterception 接口以支持上下文菜单截取。
注册和删除截取程序
com.sun.star.ui.XContextMenuInterception 接口使开发者可以注册和删除截取程序代码。截取程序注册后,会在要执行上下文菜单时得到通知。注册截取程序可以将该程序添加到截取程序链的前面,因此它会最先被调用。删除顺序是随机的。不一定要先删除最后注册的截取程序。
编写截取程序
通知
上下文菜单截取程序可以实现 com.sun.star.ui.XContextMenuInterceptor 接口。此接口含有一个函数,要执行上下文菜单时,相应的控制器就会调用该函数。
ContextMenuInterceptorAction notifyContextMenuExecute ( [in] ContextMenuExecuteEvent aEvent)
com.sun.star.ui.ContextMenuExecuteEvent 是一个保存截取程序所有重要信息的结构。
com.sun.star.ui.ContextMenuExecuteEvent 的成员 | |
---|---|
ExecutePosition | com.sun.star.awt.Point。含有将要执行的上下文菜单的位置。 |
SourceWindow | com.sun.star.awt.XWindow。含有请求上下文菜单时所在的窗口。 |
ActionTriggerContainer | com.sun.star.container.XIndexContainer。被截取的上下文菜单的结
构。该成员可以实现 com.sun.star.ui.ActionTriggerContainer 服务。 |
Selection | com.sun.star.view.XSelectionSupplier。提供源窗口中的当前选定内容。 |
查询菜单结构
ActionTriggerContainer
成员是上下文菜单条目的索引容器,其中的每个菜单条目均为一个属性集。它可以实现 com.sun.star.ui.ActionTriggerContainer 服务。com.sun.star.container.XIndexContainer 接口通过方法直接访问被截取的上下文菜单结构,以访问、插入、删除和替换菜单条目。
ActionTriggerContainer
成员中的所有元素均支持 com.sun.star.beans.XPropertySet 接口以获取和设定属性值。有两种不同类型的菜单条目含有各种属性集:
Type of Menu Entry | Service Name |
---|---|
Menu entry | "com.sun.star.ui.ActionTrigger "
|
Separator | "com.sun.star.ui.ActionTriggerSeparator "
|
确定每个菜单条目的类型是非常必要的,因为这将有助于查询接口 com.sun.star.lang.XServiceInfo 的菜单项以及调用
boolean supportsService ( [in] string ServiceName )
以下示例显示了一个用于确定正确菜单条目类型的小帮助程序类。
// A helper class to determine the menu element type public class MenuElement { static public boolean IsMenuEntry( com.sun.star.beans.XPropertySet xMenuElement ) { com.sun.star.lang.XServiceInfo xServiceInfo = (com.sun.star.lang.XServiceInfo)UnoRuntime.queryInterface( com.sun.star.lang.XServiceInfo.class, xMenuElement ); return xServiceInfo.supportsService( "com.sun.star.ui.ActionTrigger" ); } static public boolean IsMenuSeparator( com.sun.star.beans.XPropertySet xMenuElement ) { com.sun.star.lang.XServiceInfo xServiceInfo = (com.sun.star.lang.XServiceInfo)UnoRuntime.queryInterface( com.sun.star.lang.XServiceInfo.class, xMenuElement ); return xServiceInfo.supportsService( "com.sun.star.ui.ActionTriggerSeparator" ); } }
图 4.1:确定菜单元素类型 Figure 4.1: Determine the menu element type
可选菜单条目支持的 com.sun.star.ui.ActionTrigger 服务具有以下属性:
com.sun.star.ui.ActionTrigger 的属性 | |
---|---|
Text | 字符串型。含有菜单条目标签的文字。 |
CommandURL | 字符串型。含有命令 URL,命令 URL 用于定义用户选择某菜单条目时要执行的功能。 |
HelpURL | 字符串型。此可选属性含有指向帮助文本的帮助 URL。 |
Image | com.sun.star.awt.XBitmap。此属性含有显示在菜单标签左侧的图像。此属性可选,这样,如果该成员没有初始化,则不使用图像。 |
SubContainer | com.sun.star.container.XIndexContainer。此属性含有一个可选的子菜单。 |
com.sun.star.ui.ActionTriggerSeparator 服务只定义了一个可选属性:
com.sun.star.ui.ActionTriggerSeparator 的属性 | |
---|---|
SeparatorType | com.sun.star.ui.ActionTriggerSeparatorType。指定分隔符的具体类型。当前
可以使用以下类型:
|
更改菜单
不实现上下文菜单截取程序中的代码也可以完成某些任务,例如阻止激活上下文菜单。通常,更改上下文菜单是为了向用户提供其他功能。
如前面所述,上下文菜单结构通过 ActionTriggerContainer
成员进行查询,该成员是 com.sun.star.ui.ContextMenuExecuteEvent 结构的一部分。 com.sun.star.ui.ActionTriggerContainer 服务具有创建 com.sun.star.ui.ActionTriggerContainer、com.sun.star.ui.ActionTrigger 和 ActionTriggerSeparator 对象的附加接口 com.sun.star.lang.XMultiServiceFactory。这些对象可用于扩展上下文菜单。
ActionTriggerContainer 实现的 com.sun.star.lang.XMultiServiceFactory 实现支持以下字符串:
The com.sun.star.lang.XMultiServiceFactory implementation of the ActionTriggerContainer implementation supports the following strings:
字符串 | 对象 |
---|---|
"com.sun.star.ui.ActionTrigger" | 创建普通的菜单条目。 |
"com.sun.star.ui.ActionTriggerContainer" | 创建空子菜单1。 |
"com.sun.star.ui.ActionTriggerSeparator" | 建立未指定的分隔符 2。 |
1 子菜单无法单独存在。它必须插在 com.sun.star.ui.ActionTrigger 中!
2 分隔符没有特殊的类型。呈现未指定的分隔符是具体实现的任务。
完成截取
每个被调用的截取程序都会在调用返回后引导控制器继续操作。枚举 com.sun.star.ui.ContextMenuInterceptorAction 定义了可能的返回值。
com.sun.star.ui.ContextMenuInterceptorAction 的值 | |
---|---|
IGNORED
|
被调用的对象忽略了此调用。应该通知下一个注册的 com.sun.star.ui.XContextMenuInterceptor。 |
CANCELLED
|
不能执行上下文菜单。不会调用剩余的截取程序。 |
EXECUTE_MODIFIED
|
上下文菜单已更改并应执行,但不通知下一个注册的 com.sun.star.ui.XContextMenuInterceptor 。
|
CONTINUE_MODIFIED
|
上下文菜单已被调用的对象更改。应该通知下一个注册的 com.sun.star.ui.XContextMenuInterceptor 。
|
以下示例显示了一个上下文菜单截取程序,该程序将子菜单添加到在控制器(其中已注册了该 com.sun.star.ui.XContextMenuInterceptor)上截取的菜单中。该子菜单被插在上下文菜单的最顶端。它向用户提供了帮助功能,这些功能可以通过“帮助”菜单来访问。
import com.sun.star.ui.*; import com.sun.star.lang.XMultiServiceFactory; import com.sun.star.beans.XPropertySet; import com.sun.star.container.XIndexContainer; import com.sun.star.uno.UnoRuntime; import com.sun.star.uno.Exception; import com.sun.star.beans.UnknownPropertyException; import com.sun.star.lang.IllegalArgumentException; public class ContextMenuInterceptor implements XContextMenuInterceptor { public ContextMenuInterceptorAction notifyContextMenuExecute( com.sun.star.ui.ContextMenuExecuteEvent aEvent ) throws RuntimeException { try { // Retrieve context menu container and query for service factory to // create sub menus, menu entries and separators com.sun.star.container.XIndexContainer xContextMenu = aEvent.ActionTriggerContainer; com.sun.star.lang.XMultiServiceFactory xMenuElementFactory = (com.sun.star.lang.XMultiServiceFactory)UnoRuntime.queryInterface( com.sun.star.lang.XMultiServiceFactory.class, xContextMenu ); if ( xMenuElementFactory != null ) { // create root menu entry for sub menu and sub menu com.sun.star.beans.XPropertySet xRootMenuEntry = (XPropertySet)UnoRuntime.queryInterface( com.sun.star.beans.XPropertySet.class, xMenuElementFactory.createInstance ( "com.sun.star.ui.ActionTrigger" )); // create a line separator for our new help sub menu com.sun.star.beans.XPropertySet xSeparator = (com.sun.star.beans.XPropertySet)UnoRuntime.queryInterface( com.sun.star.beans.XPropertySet.class, xMenuElementFactory.createInstance( "com.sun.star.ui.ActionTriggerSeparator" ) ); Short aSeparatorType = new Short( ActionTriggerSeparatorType.LINE ); xSeparator.setPropertyValue( "SeparatorType", (Object)aSeparatorType ); // query sub menu for index container to get access com.sun.star.container.XIndexContainer xSubMenuContainer = (com.sun.star.container.XIndexContainer)UnoRuntime.queryInterface( com.sun.star.container.XIndexContainer.class, xMenuElementFactory.createInstance( "com.sun.star.ui.ActionTriggerContainer" )); // intialize root menu entry "Help" xRootMenuEntry.setPropertyValue( "Text", new String( "Help" )); xRootMenuEntry.setPropertyValue( "CommandURL", new String( "slot:5410" )); xRootMenuEntry.setPropertyValue( "HelpURL", new String( "5410" )); xRootMenuEntry.setPropertyValue( "SubContainer", (Object)xSubMenuContainer ); // create menu entries for the new sub menu // intialize help/content menu entry // entry "Content" XPropertySet xMenuEntry = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, xMenuElementFactory.createInstance ( "com.sun.star.ui.ActionTrigger" )); xMenuEntry.setPropertyValue( "Text", new String( "Content" )); xMenuEntry.setPropertyValue( "CommandURL", new String( "slot:5401" )); xMenuEntry.setPropertyValue( "HelpURL", new String( "5401" )); // insert menu entry to sub menu xSubMenuContainer.insertByIndex ( 0, (Object)xMenuEntry ); // intialize help/help agent // entry "Help Agent" xMenuEntry = (com.sun.star.beans.XPropertySet)UnoRuntime.queryInterface( com.sun.star.beans.XPropertySet.class, xMenuElementFactory.createInstance ( "com.sun.star.ui.ActionTrigger" )); xMenuEntry.setPropertyValue( "Text", new String( "Help Agent" )); xMenuEntry.setPropertyValue( "CommandURL", new String( "slot:5962" )); xMenuEntry.setPropertyValue( "HelpURL", new String( "5962" )); // insert menu entry to sub menu xSubMenuContainer.insertByIndex( 1, (Object)xMenuEntry ); // intialize help/tips // entry "Tips" xMenuEntry = (com.sun.star.beans.XPropertySet)UnoRuntime.queryInterface( com.sun.star.beans.XPropertySet.class, xMenuElementFactory.createInstance( "com.sun.star.ui.ActionTrigger" )); xMenuEntry.setPropertyValue( "Text", new String( "Tips" )); xMenuEntry.setPropertyValue( "CommandURL", new String( "slot:5404" )); xMenuEntry.setPropertyValue( "HelpURL", new String( "5404" )); // insert menu entry to sub menu xSubMenuContainer.insertByIndex ( 2, (Object)xMenuEntry ); // add separator into the given context menu xContextMenu.insertByIndex ( 0, (Object)xSeparator ); // add new sub menu into the given context menu xContextMenu.insertByIndex ( 0, (Object)xRootMenuEntry ); // The controller should execute the modified context menu and stop notifying other // interceptors. return com.sun.star.ui.ContextMenuInterceptorAction.EXECUTE_MODIFIED ; } } catch ( com.sun.star.beans.UnknownPropertyException ex ) { // do something useful // we used a unknown property } catch ( com.sun.star.lang.IndexOutOfBoundsException ex ) { // do something useful // we used an invalid index for accessing a container } catch ( com.sun.star.uno.Exception ex ) { // something strange has happend! } catch ( java.lang.Throwable ex ) { // catch java exceptions - do something useful } return com.sun.star.ui.ContextMenuInterceptorAction.IGNORED; } }
Content on this page is licensed under the Public Documentation License (PDL). |