Menus are ubiquitous in Windows and are a convenient way of grouping related options in a tidy format particularly if there is a large number of them. Menus are usually accessed from the MenuBar which is located at the top of a window however they can be made to "popup" anywhere on the screen. A Menu is really a container for one or more Menu elements. Menu elements can be either MenuItems or other Menus (aka submenus). When a Menuitem is selected by the user then a WM_COMMAND is sent to the Menuitem's handler, if any. Submenus do not generate this message. A menu is created using:
MENU_FILE = create(Menu, text, hBitmap, parent, 0, 0, 0, 0, flags)
text is the character string that will appear in the menu.
flags can be either a single atom or sequence containing menu-specific flags.
A MenuItem is created with:
MENUITEM_OPEN = create(MenuItem, text, hBitmap, parent, 0, 0, 0, 0, flags)
MENUITEM_SEP = create(MenuItem, "-", 0, parent, 0, 0, 0, 0, flags)
When a menu is displayed the entries are displayed in a single vertical column. It is possible to show additional vertical columns by specifying MF_MENUBARBREAK or MF_MENUBREAK in the flags field when creating a new menu element. The new Menu element will appear in the menu at the top of a new column. The only difference between these last two flags is that MF_MENUBARBREAK will place a vertical line between the columns. Please note that these flags are really an attribute of a Menu or MenuItem unlike the Separator line which is a form of MenuItem. This means that these flags can be included in the creation of a Separator line but there may be no point to doing so since the result will look a bit strange in the menu, ie: A new vertical column will be formed with the Separator line right at the top of it.
Any Menu or MenuItem can be enabled or disabled using setEnable(). Text labels can be accessed for any Menu or MenuItem using getText()& setText(). Any Menu (except top-level menus) or MenuItem can be "checked" using setCheck(). If a Window is sized so that the the main Menu does not fit on a single line then it will "wrap" the excess items onto an additional line. A Menu element may be inserted into a Menu using :
function insertMenu(object item, integer pID, integer pos, atom flags)
pID - id of the destination Menu
pos - position that the item is to be inserted at. If pos is 0 then the item will be put at the end of the Menu
flags - additional flags you may wish to specify. These are the same as are used when a menu element is created
If the function succeeds it will return the id of the Menu inserted or the id of the new MenuItem (created &) inserted. Otherwise it returns 0. Please note that ARWEN will not allow MenuItems to be inserted into a top-level menu. According to Petzold "Top-level items without popups can be too easily chosen by mistake." so I am enforcing this apparent limitation. From a programming perspective a MenuItem in a top-level menu is actually a Menu without an associated popup menu and it possibly could be quite awkward to maintain code for this though I don't know this from experience. Any Menu element may be removed from a Menu using:
function removeMenu(integer id)
function destroy(integer id)
To trap messages (WM_COMMAND of course) from inserted MenuItems you can do so by setting up a handler for the parent Menu OR set up a handler for the Menu element when the insertion is made. I think the latter way is the most secure thing to do. Any menu (dropdown, submenu or unowned) can be accessed with the trackPopupMenu() function which will, well, popup a menu where you have clicked on the application window, eg:
void = trackPopupMenu( id, window, flags )
flags are any combination of Button and Mode, ie: Button - TPM_LEFTBUTTON or TPM_RIGHTBUTTON Mode - TPM_LEFTALIGN, TPM_CENTERALIGN or TPM_RIGHTALIGN (If you put 0 in the flags field then you will get the standard behaviour. I may drop these flags in the future, we'll see.) To use trackPopupMenu() I trap WM_RBUTTONDOWN message in the Window handler routine and then make the call as above. You could just as easily trap the WM_LBUTTONDOWN message, in fact any message you like such as,say, keystrokes. Apparently the proper way is to trap the WM_CONTEXTMENU message in the owner window handler. I use the current mouse coordinates to dictate where the menu will popup on the screen because that is the expected behaviour (and is natural since menus are accessed with the mouse etc..) but does anyone out there want more flexibility so that they can force the popup to appear anywhere on the screen (not just the window y' know) ? When the call is made to trackPopupMenu() then it doesn't return until the popup has closed. In one way it is like the Dialog windows.
At times the user may wish to treat a common group of MenuItems in a similar way to the behaviour of RadioButtons where one item can be marked to the exclusion of all other items in the group. You can use this procedure for MenuItems:
checkMenuRadioItem(integer id, integer first, integer last)