Liberty Basic is develeopped by Carl Gundel
Original Newsletter compiled by Alyce Watson and Brosco
Translation to HTML: Raymond Roumeas

The Liberty Basic Newsletter - Issue #44 - JUL 99

"Knowledge is a gift we receive from others." - Michael T. Rankin

In this issue:

Menus - Part 1

In future issues:


Menus - Part 1:

 

Liberty BASIC MENUS Syntax and usage.

 

Menu API calls: the basics

Getting handles to menus and menu items.

Removing the MenuBar.

 

Menu API calls: intermediate

Change string$

Enable/disable menu items.

Check menu items.

Menu Radio Buttons.

Check menu items with bitmap.

Use bitmap as menu item.


Liberty BASIC MENUS: Syntax and usage

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.


Menu API calls: the basics

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.


Getting handles to menus and menu items.

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


Removing the MENU BAR

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


Menu API calls: intermediate

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.


Change string$

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 GetMenuItemID
Menu.Name$ as ptr,_ 'new string$ - name of menu item
result 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


Enable/disable menu items.

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


Check menu items.

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


Menu Radio Buttons.

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


Check menu items with bitmap.

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


Use bitmap as menu item.

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


Newsletter compiled and edited by: Brosco and Alyce.

Comments, requests or corrections: Hit 'REPLY' now!

mailto:brosc-@orac.net.au

or

mailto:awatso-@mail.wctc.net