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.
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.
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.
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.
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:
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 )
<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)
// 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
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.
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)
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 )
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 )
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).