Use the menu routines to display traditional toplevel or pop-up style menus. Be sure to read the introductory chapter that follows, and the entries on the MENU and MENUITEM structures. A lot of what PAL menus can do is controlled in the data that describes them, there are only a few functions.
Available functions:
HandleMenu
: Display a menu and start user interaction
MenuSelect
: Simple interface for pop-up style menus
SEE ALSO: MNU Introduction MENU MENUITEM HandleMenu MenuSelect
#include <stdlib.h>
#include "pal.h"
/* note that the menu item return values are defined in such a
way as to directly return the corresponding baud rate
This works for baudrates below 32767 since the return
value is an int ... */
MENUITEM BaudMnuItms[] = {
{ " 300", MA_VAL , MENUVAL(300) },
{ " 1200", MA_VAL, MENUVAL(1200) },
{ " 2400", MA_VAL, MENUVAL(2400) },
{ " 9600", MA_VAL, MENUVAL(9600) },
{ "19200", MA_VAL, MENUVAL(19200) },
};
MENU BaudMenu = { NULL, 0, 0, 0, 5, 5, BaudMnuItms };
int SetBaud(int Baud)
{
int Selection;
/* get selection from user */
Selection = HandleMenu(&BaudMenu, 200, 20);
/* if the user hit ESC, Selection will be negative,
in this case, keep old Baud rate */
if(Selection > 0) {
/* set new baudrate if selection wasn't aborted */
Baud = Selection;
}
return Baud;
}
See the description of the MENU and MNUITEM structure for
details on menu definition and more advanced usage of menues,
like pulldowns, separators, bitmaps/icons in menues etc.
Note that you can also call the new MenuSelect function (see
below) to have a simpler interface.MENU
A menu structure describes a menu in PAL - you provide a
pointer to such a structure when calling HandleMenu. This
structure itself has a pointer to an array of 'menu items'
- while the MENU structure provides general information
about the menu (like whether it should display
horizontally or vertically), the MENUITEM array describes
the different items that are part of a menu. See below for
a description of the MENUITEM structure. /* menu descriptor structure */
typedef struct {
PALWIN *pMnuWin; /* a menu has an associated window */
WORD Flags; /* flags: kind of menu */
int CurItem; /* currently selected item */
int TopItem; /* first visible item in menu */
int ItmDisp; /* number of visible items */
int ItmCount; /* total number of items */
MENUITEM *Items; /* array of items */
} MENU;
FIELDS
PALWIN *pMnuWin - If this field is NULL in your menu
definition (usually the case) then
HandleMenu will create a window for your
menu when called. It will otherwise use
the window you provide. (It will NOT
close it upon termination in this case)
WORD Flags - This field has constants ored together
that control various characteristics of
a menu:
MS_HORIZ - add this constant if you want a
horizontal menu. The menu bar of an
application should also have the next
attribute, MS_TOPLVL. ('Or' them together
like so: MS_HORIZ|MS_TOPLVL )
Menus are vertical by default - to get
a vertical menu, you don't need to do
anything special.
MS_TOPLVL - add this constant to the toplevel menu
(bar) of a hierarchical menu structure
so that HandleMenu can handle it
correctly.
MS_PULLDN - add this constant to a pulldown menu
that is part of, but not the top level
of a hierarchical menu structure.
int CurItem - usually initialized to zero, this is the
currently active menu item. If you are
using a menu to present a picklist to
the user (as in the example above, in
the general discussion of menu support),
you could use this field to set up the
default choice.
int TopItem - usually initialized to zero, this value
is used in scrolling menues to identify
the first item visible in the menu
window.
int ItmDisp - this is the number of menu items that
should be visible in the menu window. If
you want all your items to be visible,
set this field to the same value as the
next one, ItmCount. Otherwise, only the
number given is shown, and your menu
will scroll. Note that all items must
be of the same height (width) for a
scrolling vertical (horizontal) menu to
work correctly.
int ItmCount - this field tells how many items are
present in the item array.
MENUITEM *Items - This is the pointer to your array of
menu items. See below for an example,
and also see the MENUITEM entry for
details on thos Take care that the following are true when defining a menu
structure:
+ ItmDisp <= ItmCount
+ TopItem <= CurItem < TopItem + ItmDisp Here's a complete example of an application menu bar that
has two pulldowns. It will look like this on the screen:
+-------------------------------------------+
| File Sample |
+-------+-+--------+------------------------+
| Exit | | First |
+-------+ | Second |
| Third |
+--------+
And here are the definitions necessary to create the
whole thing. Note that there are three menus involved
here: one horizontal, and two vertical ones.
/* define the constants for the menues */
enum { CMD_EXIT, CMD_FIRST, CMD_SECOND, CMD_THIRD };
/* define items and menu of the 'File' pulldown */
MENUITEM FileMnuItms[] = {
{ " Exit ", MA_VAL, MENUVAL(CMD_EXIT) },
};
MENU FileMenu[] = { NULL, MS_PULLDN, 0, 0, 1, 1, FileMnuItms };
/* define items and menu of the 'Sample' pulldown */
MENUITEM SampleMnuItms[] = {
{ " First ", MA_VAL, MENUVAL(CMD_FIRST) },
{ " Second ", MA_VAL, MENUVAL(CMD_SECOND) },
{ " Third ", MA_VAL, MENUVAL(CMD_THIRD) },
};
MENU SampleMenu[] = { NULL, MS_PULLDN, 0, 0, 3, 3, SampleMnuItms };
/* define items and menu of the top level menu bar */
MENUITEM TopMnuItms[] = {
{ " File ", MA_MNU, &FileMenu },
{ " Sample ", MA_MNU, &SampleMenu },
};
MENU TopMenu[] = { NULL, MS_TOPLVL|MS_HORIZ, 0, 0, 2, 2, TopMnuItems };
To activate this menu, you would call
HandleMenu(&TopMenu, 10, 10); /* for example */MENUITEM
A menu item describes a building block of a menu - usually
these are horizontal or vertical lines, but can also be
separators (a horizontal or vertical line) or bitmaps.
Menu items are always grouped together in an array - the
last item structure of this array by convention having all
its fields set to zero to indicate the end of the array.
A pointer to the item array is contained in the MENU
structure. /* menu item descriptor structure */
typedef struct {
char *Text; /* Text to be displayed */
WORD Flags; /* flags: state item is in, action triggered */
void *ActionPtr; /* additional parameter for action */
} MENUITEM;
FIELDS
char *Text - Points to the text of the menu item.
Exception: if the item is of type
'bitmap' (MT_BMP flag, see below), this
is a pointer to the bitmap definition.
If the item is of type 'separator'
(MT_SEP flag), then this field is
ignored.
WORD Flags - This field has constants ored together
that control the aspect, the type, and
the action triggered by a menu item:
Flags controlling type: start with MT_
MT_TXT: your regular, one line of text, menu item
MT_SEP: a horizontal or vertical separating line
(Note: Use the predefined MT_SEPARATOR that
also prevents the cursor from being moved to
a separator)
MT_BMP: a bitmap or icon. 'Text' in this case points
to an IMGHDR structure defining the bitmap.
(See the LoadImg and LoadPcx functions also)
Flags controlling aspect and behaviour: start with MI_
MI_GRY: The menu item should appear grayed
MI_SKIP: The cursor should avoid this menu item
(jump over it)
Flags controlling the action triggered by a menu item
when selected. They start with MA_
MA_VAL: Most common: menu item will return a
value when selected. The value is defined
in the next field, ActionPtr.
MA_MNU: The menu item will call another menu when
selected. The next field, ActionPtr, should
be the pointer to this menu.
MA_FUN: When selected, the menu item will call a
function pointed to by ActionPtr. See the
ActionPtr description below for details.
void *ActionPtr - This field's interpretation varies
according to the action associated with
the menu item.
+ if the menu item has an 'action' flag of MA_VAL,
ActionPtr is not a pointer at all - instead, it
holds the value that should be returned by the item
when selected. To keep the C compiler from
complaining about such an assignment, use the
MENUVAL() macro provided by PAL.H to convert a int
into an acceptable 'pseudo-pointer'. Here's an
example of such an item initialization:
{ " Exit ", MA_VAL, MENUVAL(999) }
+ if the menu item has an 'action' flag of MA_MNU,
ActionPtr should point to the menu that pops up when
this item is selected. Here's an example:
{ " Settings -> ", MA_MNU, &MnuSettings }
+ if the menu item has an 'action' flag of MA_FUN,
ActionPtr should be a pointer to the function to be
called when the item is selected. This function has
the following prototype:
int Callback(MENU *pMnu);
The PAL HandleMenu routine will pass a pointer to
the current menu to it. The function can find out
which menu item triggered it (in case there are
several calling the same function) by inspecting
pMnu->CurItem. (Resp. pMnu->Items[pMnu->CurItem]).
Your callback function should return:
- a positive integer if it wants this value to be
returned to the HandleMenu caller (as if the menu
item were of type MNU_VAL and returned this value)
- the special constant MSC_STAY if it wants the
HandleMenu to stay in the menu loop, i.e. if the
menu should stay open.
See the MenuCallback() function in
.\SAMPLES\MENU\MENU.C for an example of a menu
callback function. you compile PAL in small or large medium model.
It is inactive in medium or compact models -
the size of a function and of a data pointer
differ in these memory models.
HandleMenu
HandleMenu displays a menu and lets the user interact with
it. It returns with a positive integer that identifies the
menu item (if any) that the user selected. In the
HandleMenu call, you specify the menu you want displayed
(by a pointer to the structure describing it), and where
it should appear on the screen.
#include "pal.h"
int HandleMenu(MENU *pMnu, int PosX, int PosY); MENU *pMenu - a pointer to the menu that you want
handled.
int PosX - X position of upper left corner of the menu
on the screen.
int PosY - Y position of upper left corner of the menu
on the screen. HandleMenu returns a positive integer if one of the
'value-returning' items got selected. It returns MSC_ESC
if the user aborted the selection. MSC_ESC is guaranteed
to be negative, so you can check on the sign of the return
value. HandleMenu(&TopMenu, 10, 10); /* for example */
(Also see the examples under "Menu support" and the description
of the MENU structure.)MenuSelect
MenuSelect provides you with a fast and easy interface to
the menu routines. You pass a string with items separated
by '|', and it will construct a menu, show it to the user,
and return the index of the selected item. You can also
specifiy where the menu should show up, which item should
be highlighted by default, and how many items to show.
(The menu will scroll if this is less than the total number
of items) #include "pal.h"
int MenuSelect(char *Items, int PosX, int PosY, int Default, int Show); Items - The string with the menu items - separate them with '|'
PosX - X position of where the menu should be displayed
PosY - Y position of where the menu should be displayed
Default - the index of the item that should be initially highlighted
Show - the number of items to display, 0 means show all items.
(so you don't have to count them) The (zero-based) index of the item the user selected, or -1 if
he hit the ESC key. /* Have the user select a day of the week. Position the menu
at (100,20), Thursday as default, 5 visible items */
n = MenuSelect(
"Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday",
100, 20, 3, 5);