Liberty Basic is develeopped by Carl Gundel Original Newsletter compiled by Alyce Watson and Brosco Translation to HTML: Raymond Roumeas
In this issue:
Menus - Part 1
In future issues:
Liberty BASIC MENUS Syntax and usage.
Getting handles to menus and menu items.
Menus will appear on a gray bar (the menu bar!) just under the titlebar of a window. You must list menus in your code before the OPEN window statement. The format for a menu is:
menu #w, "Top Title", "First Item", [1.branch],_ "Second Item", [2.branch]
You may add as many items as you like, but the menu statement MUST ALL BE ON ONE LINE! All Liberty Basic commands must be on a single line - but it is possible to use multiple lines by using the continuation character:
menu #w, "Top Title", _ ' The underscore is the CONTINUATION symbol "First Item", [1.branch], _ "Second Item", [2.branch]
The "Top Title" is the only part of the menu that will appear on the menu bar until the user clicks the mouse there. Then, the entire menu will drop down and the user can choose any of the items. The program will then continue execution at the branch label that has been designated for the chosen menu item.
Let us stop here and define terms. The gray bar that appears just below the titlebar of a window is the MENU BAR. The choices that are listed across the MENU BAR are SUBMENUS.
The small, gray window that appears to drop down when a SUBMENU is clicked is a POPUP MENU. The items that appear on the POPUP MENU are MENU ITEMS.
Put an ampersand (&) in front of a character in your SUBMENU or in front of a character in your MENU ITEMS and that key becomes a hot key. The user can choose the alt key and the hot key to activate the MENU ITEM, instead of doing so with the mouse.
menu #w, "&SubMenu", "&Enabled Menu Item", [1.branch],_ "&Disabled Menu Item", [2.branch], | , "E&xit", [exit]
In the above example hitting alt-S activates the POPUP MENU. Then, while continuing to hold down the alt key, hitting E activates the first item and the program will go to [1.branch], hitting D activates the second item, or hitting X activates the [exit] routine. Hot keys are case insensitive, so activating alt-S is the same as alt-s. Notice that your ampersand needn't be in front of the first character in a word to work - X is the second character in the word EXIT. Notice also that you want unique letters in each item for a hot key. If you designate T as a hot key in the first item, don't use T for a hot key in any other item. Although the ampersand appears in your code, it will not appear within words in your program. The character immediately following the ampersand in the code will be underscored to show the user that it is a hot key.
You may include as many SUBMENUS as you need in your program.
If they do not all fit across the top of a window, Windows will make the MENU BAR deeper and you will have more than one row of SUBMENUS.
You may place a dividing line between MENU ITEMS, so as to group them together for a more professional look. You simply place the character ( | ) between commas. That tells Windows to place a MENU BREAK in that position. In the following example, a MENU BREAK will appear before the "Sec&ond Item."
menu #w, "&Top Title", "&First Item", [1.branch],|,_ "Sec&ond Item", [2.branch]
DIALOG BOXES
DIALOG BOXES do not have menus, so don't try to put one there! You will need to handle user choices in other ways, such as buttons or comboboxes if you use a dialog box.
TEXT WINDOWS
If your window is of type-TEXT, Liberty BASIC gives you a complete FILE menu, with open, print, etc. and a complete EDIT menu, with cut, paste, etc. You do not need to designate these menus. You cannot remove them either! The user can access the EDIT menu with a right mouse click, making a nice, professional application. You can add as many other menus to your TEXT WINDOW as you want.
TEXT EDITOR CONTROL
If you add a text editor control to a window, it will automatically add a complete EDIT menu to the menu bar. You do not need to designate it yourself, nor can you remove it. As with the TEXT WINDOW, you can access the edit menu with a right mouse click. You can add as many other menus to the window as you want.
There are quite a few ways to manipulate Liberty BASIC menus via the API. To use them, you must first obtain handles (ID's) to the MENU BAR, SUBMENUS and MENU ITEMS that will be modified.
For most MENU API calls, you will need to obtain a handle to the MENU BAR. GetMenu is the call that returns the MENU BAR HANDLE:
[Menu.Init] 'Gets handle of menu bar CallDll #user, "GetMenu", _ hMain as word,_ 'handle of nongraphics window, or parent 'handle of graphics window hMenuBar as word 'returns handle of MENU BAR
After you get the handle of the MENU BAR, you may get the handles of any of the SUBMENUs that it contains with a call to GetSubMenu. A SUBMENU appears on the menu bar, and when clicked, its POPUP MENU drops down. You need to pass the parameter specifying the position of the SUBMENU, so please note that the first SUBMENU on the left side of the MENUBAR is in Position 0:
[GetSubMenu] CallDll #user, "GetSubMenu", hMenuBar as short,_ 'handle of MENU BAR nPos as short,_ 'position of menu:0 is in the first position, '1 is the second, etc. hSubMenu as short 'handle of submenu
Once you have the handle of the SUBMENU, you can get the handles of all of the MENU ITEMS on its POPUP MENU with a call to GetMenuItemID. You will need the handles of these items for many of the menu api calls. Please note that the parameter nPos, which specifies the position of the MENU ITEM desired counts positions from 0. The first MENU ITEM has position 0, the second has position 1 and so on.
[GetMenuItemID] CallDll #user, "GetMenuItemID", _ hSubMenu as word, _ ' handle of the submenu nPos as short, _ 'position of the menu item on the popup menu menu.id as word 'the handle (or ID) of the menu item
There is one way to remove the FILE and EDIT menus from a text window. It requires that you remove the entire MENU BAR. You need the handle of the window, in order to make the API call that removes the MENU BAR. This is usually obtained with LB's HWND function:
hMain = HWND(#main)
If the program window is a graphics window, however, this presents a special case. You must first obtain the handle of the graphics window, then use that to make a call to GetParent, and use the handle returned by that call in your subsequent API calls. Examples of a graphics window and a nongraphics window follow:
[GraphicsWindow] OPEN "No Menu Here!" for graphics as #main hMain = HWND(#main) CallDLL #user, "GetParent", _ hMain AS word, _ 'handle of graphics window hParent AS word 'returns parent window handle [Menu.Destroy] 'Removes entire MenuBar calldll #user, "SetMenu",_ hParent as word,_ 'parent handle of graphics window 0 as word,_ '0 removes the MENU BAR results as ushort 'returns nonzero if successful
Note please! After this, all examples will be done in a plain window! Please make allowances if you are using a graphics window, as above!
[NonGraphicsWindow] OPEN "No Menu Here!" for graphics as #main hMain = HWND(#main) [Menu.Destroy] 'Removes entire MenuBar calldll #user, "SetMenu",_ hMain as word,_ 'handle of nongraphics window 0 as word,_ '0 removes the MENU BAR results as ushort 'returns nonzero if successful
If you made a call to GetMenu before removing the MENU BAR, you can restore it with another call to SetMenu.
[restore.menubar] CallDll #user, "SetMenu",_ 'restore the menu bar hMain as word,_ 'handle of window hMenuBar as word,_ 'handle of menubar results as ushort 'returns nonzero if successful
It is not difficult to manipulate MENU ITEMS and SUBMENUS FOR ALL API CALLS: If the flag _MF_BYCOMMAND is set, the parameter indicates the handle (ID) of the MENU ITEM. If the flag _MF_BYPOSITIOIN is set, the parameter indicates the position of the item, with 0 being the first position, 1 being the second position and so on. If neither of these flags is set by the programmer, the default _MF_BYCOMMAND, is in effect. Note also that flags are joined together with the word "or" and contain an underscore as the first character.
To change the string or text of a MENU ITEM, make a call to ModifyMenu. This call can change other attributes as well, as you will see later. This example changes the string of the MENU ITEM to be "I was changed!"
[change.menu.item.string] Menu.Name$="I was changed!" menu.flags=_MF_STRING or _MF_BYCOMMAND calldll #user, "ModifyMenu",_ hSubMenu as word,_ 'handle of SubMenu from GetSubMenu menu.id as word,_ 'ID of menu item, from GetMenuItemID menu.flags as word,_ '_MF_STRING OR _MF_BYCOMMAND menu.id as word,_ 'ID of menu item, from GetMenuItemIDMenu.Name$ as ptr,_ 'new string$ - name of menu itemresult as ushort 'returns nonzero if successful
The same call to ModifyMenu can also be used to change the string on a SubMenu - the text that names the menu on the Menu Bar. The first parameter to pass is then the handle of the Menu Bar that you got with a call to GetMenu. Then, instead of the Menu Item ID that was used in the previous call, pass the handle of the SubMenu.
[change.submenu.string] Menu.Name$="I was changed!" menu.flags=_MF_STRING or _MF_BYCOMMAND calldll #user, "ModifyMenu",_ hMenu as word,_ 'handle of Menu Bar hSubMenu as word,_ 'handle of SubMenu menu.flags as word,_ ' _MF_STRING OR _MF_BYCOMMAND hSubMenu as word,_ 'handle of SubMenu Menu.Name$ as ptr,_ 'new string$ - name of SubMenu results as ushort 'returns nonzero if successful
NOTE:
You may also call ChangeMenu, but this function has been replaced by the function ModifyMenu.
[change.menu] change.flags=_MF_CHANGE or _MF_STRING or _MF_BYCOMMAND NewName$="I was changed!" calldll #user, "ChangeMenu", _ hMenu as word, _ 'handle of Menu Bar hSubMenu as word, _ 'handle of SubMenu to change NewName$ as ptr, _ 'new string hSubMenu as word, _ 'handle of SubMenu to change change.flags as word, _ 'flags needed for the call result as word
EnableMenuItem can be one of the most useful of the menu api calls. You would want to disable a menu item at the start of a program, if that routine is not available until other functions have been performed. For instance, if no file is loaded, the menu item "Save" could be disabled, to indicate to the user that there is nothing yet to save. A disabled menu item appears in gray, rather than black. Once a file is loaded, the "Save" menu item could be enabled.
[enable.menuitem] menu.flag = _MF_DISABLED ' disables the item calldll #user, "EnableMenuItem", _ hSubMenu as word,_ 'handle of SubMenu that contains the Menu Item menu.id as word,_ 'ID of menu item menu.flag as word,_ 'enabled = _MF_ENABLED Menu.enabled.return as word 'returns previous state of menu item
It is quite easy to place a checkmark beside a menu item to give the user information about which program choices are in force.
Make a call to CheckMenuItem. If your program was made for speakers of English and speakers of German, you might have a menu item for each language. The user could see which language was current and could choose a language by clicking on the proper menu item. To make the call, you must have the handle of the submenu containing the items to be checked, and the ID of any items that might be checked.
[check.menuitem] 'wCheck=0 is value for unchecked 'wCheck=8 is value for checked calldll #user,"CheckMenuItem",_ hSubMenu As word,_ 'handle of submenu menu.id As word,_ 'ID of menu item wCheck As short,_ 'checked=8, unchecked=0 r as short
In the previous example, we discussed using language in a program, and checking the language menu items accordingly. Actually, there is a better way to handle this condition. Since only one language can be used at a time, the language menu items can all be part of a radio-group. This means that checking one item automatically UNCHECKS the other items.
The api call is to CheckMenuRadioItem. You will need the handle of the submenu and the IDs of all menu items to begin.
You will also need to specify the ID of the FIRST menu item that is part of the radio-group, and the LAST menu item that is part of the radio-group. Then you pass the ID of the menu item that is to be checked.
[radio.check.menuitem] calldll #user,"CheckMenuRadioItem",_ hSubMenu as word,_ menu.id.first as word,_ 'first item in radio group menu.id.last as word,_ 'last item in radio group menu.id as word,_ 'Item to be checked 8 as short,_ 'always 8 r as short
There is another way to check/uncheck menu items. You may use a small bmp for item-checked, item-unchecked, or both. If you will be using bitmaps as checkmarks, you must first make a call to SetMenuItemBitmaps to specify the loaded bitmaps that will be used as checkmarks. If either the hUncheckBMP or the hCheckBMP parameter is NULL, (null = 0) Windows displays nothing next to the menu item for the corresponding attribute. If both parameters are NULL, Windows uses the default check mark when the item is checked and removes the check mark when the item is unchecked.Later, the usual call to CheckMenuItem will check or uncheck the item, using the bitmaps you have set up.
Note: bitmaps used as checkmarks should have a small width and height. Try 12x12.
You may also use bitmaps for Radio Item checks, by calling SetMenuItemBitmaps in exactly the same way as the example below.
[set.bitmap.checkmarks] loadbmp "check","check.bmp" loadbmp "uncheck","uncheck.bmp" hCheckBMP = hbmp("check") hUnCheckBMP = hbmp("uncheck") calldll #user,"SetMenuItemBitmaps",_ hSubMenu as word,_ 'handle of submenu menu.id as short,_ 'ID of item to check/uncheck _MF_BYCOMMAND as word,_ 'use ID, not position hCheckBMP as word,_ 'handle of bmp for checked item hUnCheckBMP as word,_ 'handle of bmp for unchecked item results as ushort
Yes, you can use a bitmap instead of a text string as a Menu Item. Make a call to ModifyMenu to modify the menu item that will be replaced by a bitmap. If one of the flags is _MF_BITMAP your menu item will be the bitmap referenced. It is best to keep the bitmaps used for this purpose fairly small, but even large ones seem to work okay.
[make.bitmap.menuitem] loadbmp "picture","picture.bmp" hPicture = hbmp("picture") FLAGS = _MF_BYCOMMAND OR _MF_BITMAP calldll #user, "ModifyMenu",_ hSubMenu as word,_ 'handle of submenu menu.id as word,_ 'ID of menu item FLAGS as word,_ 'flags for this call menu.id as word,_ 'ID of menu item hPicture as long,_ 'handle of bmp results as ushort
(c) 1999 Cliff Bros: brosc-@orac.net.au
and
Alyce Watson: awatso-@wctc.net
Comments, requests or corrections: Hit 'REPLY' now!
mailto:brosc-@orac.net.au
or
mailto:awatso-@mail.wctc.net