'Demo for Hiding/Showing Submenus and Command Items'This example illustrates how to hide submenus and reshow them when desired. The menus are created in the normal way,'and we keep track of handles, IDs and positions to refer to later.'Terminology: Menus are basically lists of menu items. The menu bar at the top of the window is the top-level menu.'Its menu items are normally themselves menus and are called submenus. The menu items listed in a submenu, such as'the File menu, normally trigger some action, such as Save File, and are called command items. However, the File'menu could contain a submenu that opens another list. Everything is a menu item. Each menu item is either itself a menu,'or it is a command item. Every menu except the menu bar is also a submenu. We don't deal here with hiding'the menu bar, so everything we hide/show will either be a submenu or a command item. The distinction is important'mainly because submenus are referred to by their handles (and normally have IDs of -1) and command items are'referred to by their IDs (and have NULL handles).''We create a File and Options menu, and two additional menus to trigger the hiding/showing of the entire Options'menu, or the Save menu item in the File menu. Hiding/showing the Options menu illustrates how to deal with submenus.'Hiding/showing the Save menu item illustrates how to deal with command items.'declare major variablesglobal hWindow 'Windows handle to the windowglobal hMenuBar 'Windows handle to menu bar in windowglobal hFileMenu, hOptionsMenu 'Windows handles to menus we want to mess withglobal menuSaveID 'ID of Save menu itemglobal menuFilePosition, menuSavePosition, menuOptionsPosition 'Positions of these menu items in their menus, with first menu=0global showOptions, showSave 'Flags to indicate whether Options menu and Save menu item should be made visibleglobal optionsIsShowing, saveIsShowing 'Keeps track of what is actually showing nownomainwin[CreateWindow]WindowWidth=300WindowHeight=300UpperLeftX=200UpperLeftY=200'Create File, Save and Options menusmenu#handle,"File","Open",[Open],"Save",[Save]menu#handle,"Options","Calibrate",[Calibrate],"Reset",[Reset]'Create menu to hide/show entire Options menu with its command itemsmenu#handle,"Options_Mode","With Options",[WithOptions],"Without Options",[WithoutOptions]'Create menu to hide/show just the Save command item in the File menumenu#handle,"File_Mode","With Save",[WithSave],"Without Save",[WithoutSave]open"Test Window"forwindowas#handle 'Open the actual window with all menus showing'Keep track of the position of the things that need to be modified. Note that if we were possibly'hiding more than one menu in the menu bar, the position of our target menu might change based on'what else we had hidden, so we would have to keep track of that.
menuOptionsPosition=1'Options menu is second in menu bar, which is position 1 when indexed from zero
menuFilePosition=0'File menu is first in menu bar, which is position 1 when indexed from zero
menuSavePosition=1'Save menu item is second in File menu, which is position 1 when indexed from zero
hWindow=hwnd(#handle)'get window handle'Get handle to the menu bar. We could put this in a subroutine, but it will only be used once.calldll#user32,"GetMenu",_
hWindow asulong,_ 'window handle
hMenuBar asulong'returns handle of menubar'Save handle to Options menu for later reference. Because it is a submenu (i.e. it opens another'menu of choices) it is referred to by its handle)
hOptionsMenu=uSubMenuHandle(hMenuBar, menuOptionsPosition)
hFileMenu=uSubMenuHandle(hMenuBar, menuFilePosition)'Save ID of Save menu item. Because it is a command item (i.e. it triggers a command, rather than'opening another menu), it is referred to by an ID number)
menuSaveID=uMenuItemID(hFileMenu, menuSavePosition)
optionsIsShowing=1: saveIsShowing=1'Everything is showing at the moment
showSave=1: showOptions=0'Tells ConformMenusToMode to show Save and hide Optionscall ConformMenusToMode 'Hide/show whatever is indicated by showSave and showOptionsprint#handle,"trapclose [quit]"'goto [quit] if window is closedwait'Wait for user action[quit]close#handle
end'These are the actions for the File and Options menus. Here we just wait.[Open]wait[Save]wait[Calibrate]wait[Reset]wait'The following respond to clicks in the Options Mode and Save Mode menus.[WithOptions]
showOptions=1:call ConformMenusToMode
wait[WithoutOptions]
showOptions=0:call ConformMenusToMode
wait[WithSave]
showSave=1:call ConformMenusToMode
wait[WithoutSave]
showSave=0:call ConformMenusToMode
wait'ConformMenusToMode shows/hides whatever is indicated by showOptions and showSave'showOptions and showSave could be made arguments here instead of global variables.sub ConformMenusToMode
'Here we hide everything that might ever need to be hidden, and then show what we want. In this'simple example, we could first check to see that what is now shown is supposed to be shown, but'for a more involved case it is better to first hide everything that might need to be hidden.'We created two different subroutines for hiding. One is for command items like Save, which'actually trigger action and are referred to by an ID. One is for submenus like Options, which simply'open another list of choices.if saveIsShowing then menuOK=uHideCommandItem(hFileMenu,menuSaveID)'Hide Save menu item, identified by the handle of'the menu it is in and its own ID'Hide Options menu item, identified by the handle of menu it is in and its relative postion.'This hides the word "Options" in the menu bar and also the Calibrate and Reset command items'that are listed ini the Options menu. Because uHideSubMenu uses the DLL RemoveMenu, rather than DeleteMenu,'the full Options menu structure will continue to exist in memory so we can show it later.if optionsIsShowing then menuOK=uHideSubMenu(hMenuBar, menuOptionsPosition)'Now both Options and Save are hidden. If we want to show one, we do it here.'For variety, we take a different approach here. For hiding, we created separate subroutines'for command items and menus. Here, we use a single subroutine, with two different arguments, one for'the ID and one for the handle. When showing a command item, we use the ID and dummy handle. When showing'a submenu, we use the handle and a dummy ID.if showSave then
menuOK=uShowMenuItem(hFileMenu, _ 'Handle to the menu that contains the Save menu item
menuSaveID, _ 'ID of the Save menu item. We use this because Save is a command item
NULL, _ 'Dummy handle for Save menu item. We use this because command items don't have handles."Save", _ 'Caption to use for inserted menu item. We aren't changing the caption.
menuSavePosition)'Position in File menu to insert Save menu item.
saveIsShowing=1else
saveIsShowing=0endifif showOptions then
menuOK=uShowMenuItem(hMenuBar, _ 'Handle to the menu that contains the Save menu item-1, _ 'Dummy ID of Options menu. IDs are for command items, which this is not.
hOptionsMenu, _ 'handle to Options menu, which still exists in memory"Options", _ 'Caption to use for inserted menu. We aren't changing the caption.
menuOptionsPosition)'Position in menu bar to insert Options menu
optionsIsShowing=1else
optionsIsShowing=0endif'The above only affected memory structures. We need to actually draw the new menu.'This has to be done even if the window is not currently visible.'We specify the handle of the window whose menu bar is to be redrawn.call uDrawMenu hWindow
endsub'-------------------------------------------------------------------------------------------'-----The remaining subroutines are wrappers for calling Windows API functions.-------------'-------------------------------------------------------------------------------------------function uHideCommandItem(hParent, itemID)'Delete the specified command item. It can later be re-inserted'hParent is the submenu containing the item. "Parent" may not be Windows terminology.'itemID is the ID of the item to hide by removing itcalldll#user32,"RemoveMenu",_
hParent asulong,_ 'handle of submenu
itemID asulong,_ 'menu item ID
_MF_BYCOMMAND aslong,_ 'says we are specifying the target item by its ID, not its position
result aslong'nonzero=success We return this, but it probably won't be used.
uHideCommandItem=result
endfunctionfunction uHideSubMenu(hParent, position)'Delete the specified submenu. It can later be re-inserted'hParent is the submenu containing the item. "Parent" may not be Windows terminology.'postion is the position of the item to hide by removing itcalldll#user32,"RemoveMenu",_
hParent asulong,_ 'handle of menu listing the one we want to hide
position asulong,_ 'position of menu we want to hide
_MF_BYPOSITION aslong,_ 'Says we are specifying the target menu by its position
result aslong'nonzero=success We return this, but it probably won't be used.
uHideSubMenu=result
endfunctionfunction uShowMenuItem(hParent, itemID, hMenu, caption$, precedeNum)'Insert a menu item that was previously deleted'hParent is the submenu in which it will be inserted'itemID is the item ID of the item to insert, if it is a command item; otherwise -1'hMenu is the handle of the submenu to insert, if the item is a submenu; otherwise NULL'caption$ is the name of the item being inserted;'The item will be inserted prior to the item in position precedeNum (0...)--That is,'once it is inserted it will occupy position precedeNum.'the number of existing items.'An alternative subroutine could be written to locate the insertion'point by the ID of the item to be preceded, rather than by position.'The DLL uses the following structure to contain info about the item to be shownstruct MENUITEMINFO,cbSize asulong,fMask asulong, _
fType asulong,fState asulong,wID asulong, _
hSubMenu asulong,hbmpChecked asulong,hbmpUnchecked asulong, _
dwItemData asulong,dwTypeData$ asptr,cch asulong'Note dwTypeData$ is ptr because we have text caption
MENUITEMINFO.cbSize.struct=len(MENUITEMINFO.struct)'length of this structure
MENUITEMINFO.fMask.struct= _MIIM_ID or _MIIM_SUBMENU or _MIIM_TYPE 'Says to process ID, submenu handle and type
MENUITEMINFO.wID.struct= itemID 'ID of command item, or any value for submenu
MENUITEMINFO.fType.struct= _MFT_STRING 'type of caption is text
MENUITEMINFO.hSubMenu.struct=hMenu 'handle to submenu being inserted, or NULL if not a submenu
MENUITEMINFO.dwTypeData$.struct= caption$ 'caption for menu. This is represented in the struct as a pointer to the text
MENUITEMINFO.cch.struct=len(caption$)'length of new caption'we don't mess here with the struct members fState, hbmChecked, hbmpUnchecked or dwItemData.'Actual DLL callcalldll#user32,"InsertMenuItemA",_
hParent asulong,_ 'handle of menu into which we are inserting. "Parent" may not be Windows terminology.
precedeNum asulong,_ 'pos of item that new item is to precede
_MF_BYPOSITION aslong,_ 'Says to find locate the insertion point by position
MENUITEMINFO asstruct,_ 'struct with item info
result aslong'nonzero=success We return this, but it probably won't be used.
uShowMenuItem=result
endfunctionsub uDrawMenu hWind 'Redraw menu after making modificationscalldll#user32,"DrawMenuBar",_
hWind asulong,_ 'window handle
result aslong'nonzero=success We don't bother to return thisendsubfunction uSubMenuHandle(hParent, subPosition)'Return handle of submenu in specified position'hParent is handle of the menu bar, or whatever menu contains the submenu'subPosition is position (0...) of the desired submenucalldll#user32,"GetSubMenu",_
hParent asulong,_ 'menu handle
subPosition aslong,_ '0-indexed pos of submenu whose handle is sought
hSub asulong'returns submenu handle
uSubMenuHandle=hSub
endfunctionfunction uMenuItemID(hSub, itemPosition)'Return ID of item in submenu in menubar'This returns -1 if the specified menu item is not a command item, so'it is pointless to use it for submenus.calldll#user32,"GetMenuItemID", _
hSub asulong, _ 'handle of the submenu
itemPosition aslong, _ 'position of the menu item
menuID asulong'the handle (or ID) of the menu item
uMenuItemID=menuID
endfunction