Tips_gui   >   Menus   >   Context Menus
Context menus are great for adding optional commands and features to your application. They are especially appreciated by power users who are more familiar with your application.
Rather than cluttering up the window with too many buttons, use context menus. (Right-click on this field in the
to see its context menu.)If a window object supports context menus it will have a $contextmenu property. If you enter a valid menu class name in the $contextmenu property, the menu class will be opened if the user right-clicks on the window object.
Creating and maintaining a menu class for each context menu is a lot of work. A solution is to create all your context menus on-the-fly. This section explains how you can build a context menu on-the-fly.
A user interface problem with context menus is how do you communicate to the user that a context menu is available to them for certain window objects? See the topic for a technique to hint the user when a context menu exists.When the user right-clicks on a window object which has a $contextmenu a $event message is sent to the window object, pEventCode is set to evOpenContextMenu, and pContextMenu is reference to the menu instance which is about to appear to the user as a context menu.
By creating a menu class with no menu lines and adding a couple of public methods to the menu class we are able to very easily create context menus on-the-fly.
Because the menu lines are added to the menu instance we never have to make change to the menu class. A single menu class can be use for all of the context menus in an application.
If you have StudioTips a copy of the context menu and a demo is included in the StudioTips library. You are free to copy the menu class to your own applications.
The following topics explain the methods and code involved in creating context menus on-the-fly.You will need to create a menu class with a few basic methods. For this discussion the menu class is named mContextMenu.
There are no menu lines and the menu title is left empty. We just need to add the following class methods to mContextMenu.
The following class methods are added to mContextMenu.
Sample code for each of the context menu class methods is as follows:
; $addMenuLine(pName,pText,pbElipsis)
; Append ... to the pText if pbElipsis is set to true. Default is false.
Calculate Text as con(pText,pick(pbElipsis=1,'','...'))
; Add a menu line object to the menu instance.
; $add(cText,bEnabled,bChecked)
Do $cinst.$objs.$add(Text,kTrue,kFalse) Returns rMenuLine
; Assign the name to the menu item.
Do rMenuLine.$name.$assign(pName)
; Return a reference to the added menu item.
Quit method rMenuLine
; $attachEventsObserver(pfrObserver,pCallBackMethod)
; Store a reference to the the observer. Could be a window object or a window class instance.
Set reference irObserver to pfrObserver.$ref
; Store the call back method name.
Calculate iCallBackMethod as pCallBackMethod
Quit method kTrue
; $control
; The $control method is automatically called if the user selects a menu line.
; Send a call back message to the observer. Include the name of the selected menu line name as the first parameter.
Do irObserver.[iCallBackMethod]($cobj().$name)
Quit method kTrue
The window object (field) which you want to add a context menu to must have the $contextmenu property set to the name of the context menu you want to instantiate. e.g. mContextMenu. If the menu class is in another library you would need to prefix the menu class name with the library name.
When the user right-clicks on the window object Omnis Studio sends a $event message to the window object. You need to trap On evOpenContextMenu in the $event method of the window object, attach the window object (or window class) as an observer, and then add menu line(s) to the context menu instance. Sample code is as follows:
; $event method of a window object. Automatically called when the user right-clicks on the field.
On evOpenContextMenu
; Add this field as an observer to be notified if the user selects a context menu line.
; Note: Sending $cinst as the observer would result in the call back message being sent to the window class method.
Calculate CallBackMethod as '$eventContextMenuLineSelected'
Do pContextMenu.$attachEventsObserver($cobj,CallBackMethod)
; Add menu lines to the context menu.
Do pContextMenu.$addMenuLine('pingMe','Send Test Ping Message')
Do pContextMenu.$addMenuLine() ;; Empty line.
Do pContextMenu.$addMenuLine('helloWorld',"Hello World",kTrue)
You also need to add the specified call back method to the window object. Sample code is as follows:
; $eventContextMenuLineSelected(pName)
; This method is called by the $control method of the context menu if the user selected a line in the context menu.
Switch low(pName)
Case 'pingMe'
OK message [sys(85)] (Icon) {Ping message received.}
Case 'helloworld'
OK message [sys(85)] (Icon) {Hello World!}
Default
OK message [sys(85)] (Icon) {Error. Switch/case not set up for [pName]}
End Switch
Quit method kTrue
That's all there is to it! I use this technique in all of my applications and love it. Just one menu class for an infinite number of context menu. All context menu lines are added on-the-fly. You can include If/Else logic if in your $event method to include/exclude menu lines based on the state of the window or the current user.
Press the button in the to try out a context menu on-the-fly demo.The summary of context menu on-the-fly events as they occur are as follows:
One of the pitfalls of context menus is that the user might not realize a context menu exists.
How do you communicate the presence of a context menu to the user? You could add an audio message that says: Hey, this object has a context menu which you can use!, but that might get annoying to the user. Rephrase - that would be annoying.
You could add a tooltip to the field which says: Right-click for more options". The would still be annoying to the user, just less annoying.
The solution which I use it so change the cursor to a context menu cursor icon when the mouse passes over any field which has a context menu.
This is accomplished by setting the $cursor property of the field whenever you set to $contextmenu of the field.
I use one type of context menu cursor for text entry fields and another for non-text entry fields.
Omnis Studio doesn't include any context menu cursor icons so I created then in the icons editor. They are included with StudioTips. One is an I-bar style cursor for text entry fields, and the other is an arrow style cursor for non-text entry fields. The context menu of the cursor icon is blue so the user can notice it is different than the standard black MacOS context menu cursor.
Press the
The icons are stored in the button in the window to see what the context menu cursors look like.#ICONS class of the tipsDocs library which is included with StudioTips. The cursors are located on the page. For information on copying icons from one library to another refer to the Omnis Studio documentation.