Older Version Newer Version

swetterlin swetterlin Jan 25, 2010

[[code format="vb"]] '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 variables global hWindow 'Windows handle to the window global hMenuBar 'Windows handle to menu bar in window global hFileMenu, hOptionsMenu 'Windows handles to menus we want to mess with global menuSaveID 'ID of Save menu item global menuFilePosition, menuSavePosition, menuOptionsPosition 'Positions of these menu items in their menus, with first menu=0 global showOptions, showSave 'Flags to indicate whether Options menu and Save menu item should be made visible global optionsIsShowing, saveIsShowing 'Keeps track of what is actually showing now nomainwin [CreateWindow] WindowWidth = 300 WindowHeight = 300 UpperLeftX = 200 UpperLeftY = 200 'Create File, Save and Options menus menu #handle, "File", "Open", [Open], "Save", [Save] menu #handle, "Options", "Calibrate", [Calibrate], "Reset", [Reset] 'Create menu to hide/show entire Options menu with its command items menu #handle, "Options_Mode", "With Options",[WithOptions], "Without Options", [WithoutOptions] 'Create menu to hide/show just the Save command item in the File menu menu #handle, "File_Mode", "With Save", [WithSave], "Without Save", [WithoutSave] open "Test Window" for window as #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 as ulong,_ 'window handle hMenuBar as ulong '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 Options call ConformMenusToMode 'Hide/show whatever is indicated by showSave and showOptions print #handle, "trapclose [quit]" 'goto [quit] if window is closed wait '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=1 else saveIsShowing=0 end if if 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=1 else optionsIsShowing=0 end if '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 end sub '------------------------------------------------------------------------------------------- '-----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 it calldll #user32, "RemoveMenu",_ hParent as ulong,_ 'handle of submenu itemID as ulong,_ 'menu item ID _MF_BYCOMMAND as long,_ 'says we are specifying the target item by its ID, not its position result as boolean 'nonzero=success We return this, but it probably won't be used. uHideCommandItem=result end function function 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 it calldll #user32, "RemoveMenu",_ hParent as ulong,_ 'handle of menu listing the one we want to hide position as ulong,_ 'position of menu we want to hide _MF_BYPOSITION as long,_ 'Says we are specifying the target menu by its position result as boolean 'nonzero=success We return this, but it probably won't be used. uHideSubMenu=result end function function 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 shown struct MENUITEMINFO,cbSize as ulong,fMask as ulong, _ fType as ulong,fState as ulong,wID as ulong, _ hSubMenu as ulong,hbmpChecked as ulong,hbmpUnchecked as ulong, _ dwItemData as ulong,dwTypeData$ as ptr,cch as ulong '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 call calldll #user32, "InsertMenuItemA",_ hParent as ulong,_ 'handle of menu into which we are inserting. "Parent" may not be Windows terminology. precedeNum as ulong,_ 'pos of item that new item is to precede _MF_BYPOSITION as long,_ 'Says to find locate the insertion point by position MENUITEMINFO as struct,_ 'struct with item info result as boolean 'nonzero=success We return this, but it probably won't be used. uShowMenuItem=result end function sub uDrawMenu hWind 'Redraw menu after making modifications calldll #user32, "DrawMenuBar",_ hWind as ulong,_ 'window handle result as boolean 'nonzero=success We don't bother to return this end sub function 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 submenu calldll #user32, "GetSubMenu",_ hParent as ulong,_ 'menu handle subPosition as long,_ '0-indexed pos of submenu whose handle is sought hSub as ulong 'returns submenu handle uSubMenuHandle=hSub end function function 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 as ulong, _ 'handle of the submenu itemPosition as long, _ 'position of the menu item menuID as ulong 'the handle (or ID) of the menu item uMenuItemID=menuID end function [[code]]