Context Menus in OpenInsight 10 - Part III
Published 23 AUG 2017 at 12:19:34PM
To finish off this short series on context menus we're going to take a look a couple of new control methods, and also some new functionality in the ContextMenu stored procedure.
The ATTACHMENU method
successFlag = exec_Method( ctrlEntID, "ATTACHMENU", menuID )
As mentioned in the previous post, context menus are not usually created until they are needed, after which they are cached and made ready for subsequent use. If the context menu supports accelerator keys (like the one used with the group selection control in the Form Designer) this is a problem, as there is nothing for the system to scan when looking for a keystroke handler. Instead of waiting for the user to right click on a control the menu may be created without being displayed using the ATTACHMENU method. This task is normally performed in the CREATE event for specific controls that need it.
Parameters
- MenuID - This is the fully qualified repository ID of a context menu to attach. It defaults to the contents of the control's CONTEXTMENU property.
Returns
- TRUE$ if the menu is attached successfully, or FALSE$ otherwise.
Even though the menu is not displayed it still progresses through the standard INITCONTEXTMENU and CONTEXTMENU events as described in Part II. This is when the aforementioned AttachOnly parameter in the CONTEXTMENU event will be set to TRUE$, and this is why you shouldn't modify it in your event handler.
The SHOWMENU method
successFlag = exec_Method( ctrlEntID, "SHOWMENU", xPos, yPos )
This method displays the control's context menu at the specified coordinates. No attempt is made by the system to provide default coordinates, so you must decide where you want the menu to appear.
Parameters
- XPos - Horizontal screen position to display the menu at.
- YPos - Vertical screen position to display the menu at
Returns
- TRUE$ if the menu is displayed successfully, or FALSE$ otherwise.
The ContextMenu stored procedure
This program has been part of OpenInsight for a while, but has been updated with some new methods to help with managing context menus in v10. The available methods are:
- ADDQUICKEVENTS
- CREATEMENU
- GETVALUE
- SETVALUE
ContextMenu ADDQUICKEVENTS method
If you dynamically add menu items during the CONTEXTMENU event you will also need to add some way of responding the MENU events raised when a user selects them. As usual you have two choices - an event script or a QuickEvent. For the former you can pass a normal script qualifier ID directly in the item's menu structure, but for latter this is not so: QuickEvents are held within the cached menu structure and therefore need special treatment. This is the purpose of the ADDQUICKEVENTS method - it takes a list of menu item IDs, along with their QuickEvent specifications, and adds them to the internal structure.
successFlag = contextMenu( ctrlEntID, | "ADDQUICKEVENTS", | menuIDs, | eventHandlers )
Parameters
- MenuIDs - This is an @vm-delimited list of menu IDs to set the QuickEvent handlers for. Note these are not fully qualified - you don't need to pass the name of the control and the ".CONTEXTMENU." prefix.
- EventHandlers - This is an @vm-delimited list of QuickEvent handler specifications for each item passed in MenuIDs. Each handler is an @svm-delimited array with the following structure:
<0,0,1> Event Type <0,0,2> Message <0,0,3> Target <0,0,4> Parameters (@tm-delimited) <0,0,5> Return Target <0,0,6> Return Message <0,0,7> Return Type <0,0,8> Return Parameters <0,0,9> Return Flags (@tm-delimited) <0,0,10> Final Type <0,0,11> Final Message <0,0,12> Final Target <0,0,13> Final Parameters (@tm-delimited) <0,0,14> Final Flags
(This is a standard QuickEvent structure and is documented more fully in the NPHANDLER_EQUATES insert record)
Returns
- TRUE$ if the events are added successfully, or FALSE$ otherwise.
Example
// This is a simple example of adding an item in the CONTEXTMENU // event and setting a QuickEvent handler for it. // // We are inserting an item just after a separator called "TEST_SEP" // and we will add a quick event for it to call the window's commuter // module when it gets selected. declare function contextMenu, rti_Convert $insert oiWin_Equates $insert npHandler_Equates $insert logical sepID = ctrlEntID : ".CONTEXTMENU.TEST_SEP" insertPos = 0 xCount = fieldCount( menuStruct, @vm ) for x = 5 to xCount ; // ignore the header fields if ( menuStruct<0,x>[1,1] == "@" ) else if ( menuStruct<0,x,MENUPOS_NAME$> == sepID ) then insertPos = x + 1 x = xCount; // break end end next if insertPos then itemID = ctrlEntID : ".CONTEXTMENU.TEST_ITEM" menuItem = "" menuItem<0,0,MENUPOS_TYPE$> = "ITEM" menuItem<0,0,MENUPOS_NAME$> = itemID menuItem<0,0,MENUPOS_TEXT$> = "Test Item" // Add the item to the menu structure menuStruct = insert( menuStruct, 0, insertPos, 0, | menuItem ) // And give it a quick event qeID = "TEST_ITEM" qeHandler = "" qeHandler<0,0,NP_MSGTYPE$> = "R" qeHandler<0,0,NP_MSG$> = "EXECUTE" qeHandler<0,0,NP_TARGET$> = @appID<1> : "*STPROCEXE**@COMMUTER" qeHandler<0,0,NP_ARGS$> = rti_Convert( "@SELF,@EVENT", ",", @tm ) call contextMenu( ctrlEntID, "ADDQUICKEVENTS", | qeID, | qeHandler ) end
ContextMenu CREATEMENU method
successFlag = CreateMenu( ctrlEntID, "CREATEMENU", menuStruct, | "", "", "", altMenuID )
This method is the same as it was in previous versions of OpenInsight. It attempts to load a context menu entity with the same name as the parent control, optionally overriding it with a passed structure.
Parameters
- ctrlEntID - Fully qualified name of the control to attach the menu to.
- menuStruct - (optional) A dynamic array containing a menu structure that overrides the stored one. This structure can be in either the old v9 format (as documented in the v9 online help), or the new v10 format as discussed in Part II.
- altMenuID - (optional) Specifies the name of the menu to load, overriding the default behaviour that assumes we are creating a menu with the same name as the parent control.
Returns
- TRUE$ if the menu was created and attached successfully, or FALSE$ otherwise. Errors are returned via the Set_Status stored procedure.
When you use this method the menu structure is parsed and cached by the control using the INITCONTEXTMENU event; it is not displayed until the user right-clicks on it (in a similar fashion to the ATTACHMENU method)
ContextMenu GETVALUE method
This is a simple helper function for inspecting values in a menu item as discussed in Part II of this series.
itemValue = contextMenu( itemID, "GETVALUE", menuStruct, itemValueIdx )
Parameters
- ItemID - Fully qualified name of the item to query.
- MenuStruct - Menu structure to parse.
- ItemValueIdx - Index of the item value to return (see OIWIN_EQUATES).
Returns
- The requested value.
ContextMenu SETVALUE method
This is a simple helper function for updating values in a menu item as discussed in Part II of this series.
origValue = contextMenu( itemID, "SETVALUE", menuStruct, itemValueIdx, | newValue )
Parameters
- ItemID - Fully qualified name of the item to query.
- MenuStruct - Menu structure to parse.
- ItemValueIdx - Index of the item value to return (see OIWIN_EQUATES).
- NewValue - New value to set.
Returns
- The original value that was replaced by the new value.
That concludes this small trilogy on context menus - hopefully you will find them much easier to use in OpenInsight 10 and be able to make more use of them in your own applications. (Disclaimer: This article is based on preliminary information and may be subject to change in the final release version of OpenInsight 10).