PAL - Quickreference: Mnu



Menu support

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


MNU Introduction

Menus are described in PAL using two types of structures: a MENU structure that holds general information on the menu that PAL should display, and an MENUITEM structure (actually, an array of these), that describes a single item of a menu. (The array describes all items of a given menu) An 'item' is simply a line of text in a menu (it can also be an icon or bitmap in PAL) that the user can select. When selected, items can do different things: most return to the caller with a return value that you specify, others spawn off further menues, and still others call a function that you specify. The toplevel 'bar' that most applications display is actually a menu - its items are arranged horizontally, and most of them spawn off further, vertical, menues. To display a menu and let the user interact with it, call: int HandleMenu(MENU *pMnu, int PosX, int PosY); It returns with an 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. You can use menus for two purposes - first, displaying the familiar menu bar with its pulldown menues. Second, menus also make it possible to present a picklist of selection choices to the user. Let's start with an example of the latter use since it is simpler. Assume you have a communication program and want the user to select a baudrate. Here's a simple-minded sample program that illustrates this use:
SAMPLE
   #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.
SEE ALSO
MENU MENUITEM HandleMenu MenuSelect

MENU structure

NAME
      MENU
DESCRIPTION
      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.
SYNOPSIS
      /* 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
NOTE
      Take care that the following are true when defining a menu
      structure:
      + ItmDisp <= ItmCount
      + TopItem <= CurItem  < TopItem + ItmDisp
SAMPLE
      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 */
SEE ALSO
MENUITEM HandleMenu MenuSelect

MENUITEM structure

NAME
      MENUITEM
DESCRIPTION
      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.
SYNOPSIS
      /* 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.
NOTE: This functionality is only supported if
            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.
SEE ALSO
MENU HandleMenu MenuSelect

HandleMenu

NAME
      HandleMenu
DESCRIPTION
      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.
SYNOPSIS
      #include "pal.h"
      int HandleMenu(MENU *pMnu, int PosX, int PosY);
INPUTS
      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.
RETURN VALUE
      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.
NOTE
SAMPLE
      HandleMenu(&TopMenu, 10, 10); /* for example */

      (Also see the examples under "Menu support" and the description
      of the MENU structure.)
SEE ALSO
MENU MENUITEM MenuSelect

MenuSelect

NAME
      MenuSelect
DESCRIPTION
      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)
SYNOPSIS
      #include "pal.h"
      int MenuSelect(char *Items, int PosX, int PosY, int Default, int Show);
INPUTS
      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)
RETURN VALUE
      The (zero-based) index of the item the user selected, or -1 if
      he hit the ESC key.
SAMPLE
      /* 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);
SEE ALSO
MENU MENUITEM HandleMenu