home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / TOTDOC.ZIP / CHAPT12.TXT < prev    next >
Encoding:
Text File  |  1991-02-11  |  57.4 KB  |  1,430 lines

  1.                                                                            Menus
  2.                                                                            Menus
  3.                                                                            Menus
  4.  
  5.  
  6.  
  7.  
  8.  
  9.          "Ninety-eight percent of the adults in this country are decent, hard-
  10.          working Americans. It's the other lousy two percent that get all the
  11.          publicity. But then we elected them."
  12.  
  13.                                                                      Lily Tomlin
  14.  
  15.  
  16.  
  17.  
  18.  
  19.  
  20.  
  21. Introduction
  22.  
  23.          You want menus, we got menus!
  24.  
  25.          The Toolkit includes three main menu types: pop-up menus, Lotus-style
  26.          menu bars and pull-down menus. All the menus can be nested many levels
  27.          deep, i.e. when the user selects an item from a menu, another menu can
  28.          be automatically displayed. You may optionally specify a description
  29.          for any menu item, and when the user highlights the item, the descrip-
  30.          tive text is automatically displayed. All the menus provide full mouse
  31.          support, and if the mouse cursor drifts across a specific item, it is
  32.          automatically highlighted. Menu items can also be selected with the
  33.          cursor keys or by pressing a menu item hotkey.
  34.  
  35.          The object hierarchy includes a number of abstract objects, as illus-
  36.          trated in figure 12.1. You should never declare an instance of type
  37.          BaseMenuOBJ, WinMenuOBJ, BarMenuOBJ or KwikPullOBJ, as these are
  38.          abstract. Use one of the following objects to display a menu:
  39.  
  40.          MenuOBJ            This object displays a simple menu in a window. This
  41.                             object is commonly used for a program's main menu
  42.                             which is displayed when the program starts.
  43.  
  44.          MoveMenuOBJ        This object is similar to MenuOBJ, except that the
  45.                             user can drag the menu around the screen to view the
  46.                             contents of the screen below.
  47.  
  48.          LotusMenuOBJ       The LotusMenuOBJ provides a 1-2-3 (or Paradox!)
  49.                             style menu bar. The user scrolls left and right
  50.                             along the menu bar.
  51.  
  52.          PullMenuOBJ        This is an "IDE-like" pull-down menu which supports
  53.                             multiple levels of sub-menus.
  54.  
  55.          EZPullArrayOBJ     This objects provides a quick and easy way of
  56.                             creating a sophisticated pull-down menu. All you
  57.                             have to do is update a string array with the
  58.                             individual item details, and instruct the Toolkit to
  59.                             display the menu.
  60.  
  61. 12-2                                                                User's Guide
  62.  
  63. --------------------------------------------------------------------------------
  64.  
  65.          EZPullLinkOBJ      This object is similar to the EZPullArrayOBJ, except
  66.                             that the menu item details are added to a linked
  67.                             list (of type DLLOBJ or descendant).
  68.  
  69.  
  70.  
  71. Figure 12.1                                                            [PICTURE]
  72. Menu
  73. Object Hierarchy
  74.  
  75.  
  76.  
  77. Common Methods
  78.  
  79.          All menus contain items, hotkeys, descriptions, and the like. The Tool-
  80.          kit's varied menu objects share a variety of common methods which are
  81.          used to construct the menu details and characteristics.
  82.  
  83.  
  84.  
  85. Adding Menu Item Details
  86.  
  87.          The following methods are used to set the individual menu details:
  88.  
  89.  
  90.          Init;
  91.  
  92.          The Init method is passed no parameters, and should be called before
  93.          any other menu method.
  94.  
  95.  
  96.          AddItem(Txt:StrVisible);
  97.  
  98.          This method is used to add an item to the menu. The method is passed
  99.          one parameter identifying the menu text to be displayed. The item
  100.          string may include embedded highlight characters to indicate that a
  101.          specific character is designated as a hot key -- refer to the WriteHi
  102.          method on page 5-3 for further information. Special strings can be
  103.          passed to force blanks or lines in the menu item list - see the note at
  104.          the end of this section.
  105.  
  106.  
  107.          The following methods may be called to further define the settings for
  108.          each item. Note, however, that the item must have been added with AddI-
  109.          tem (or AddFullItem) before these additional settings can be specified.
  110.  
  111.  
  112.          SetHK(Item:byte; HK:word);
  113.  
  114.          Any item can be assigned a hotkey, which provides a way for the user to
  115.          select the item without scrolling to the item. All the user does is
  116.          press the hotkey. The de facto standard is to use normal alphabet char-
  117.          acters as the hotkeys. (Lotus and pull-down menus support additional
  118.          hotkeys which can be pressed even when the appropriate menu is not on
  119.          display -- this subject is discussed in detail later).
  120.  
  121.  
  122. Menus Menus Menus                                                           12-3
  123.  
  124. --------------------------------------------------------------------------------
  125.  
  126.          SetMessage(Item:byte; Msg:StrVisible);
  127.  
  128.          The SetMessage method is used to define a message for an item. When the
  129.          item is highlighted, the message will be automatically displayed, and
  130.          when the user moves to a different item, the message is removed. The
  131.          Toolkit does not save the contents of the screen where the message is
  132.          displayed.
  133.  
  134.  
  135.          SetID(Item:byte; ID:word);
  136.  
  137.          In a menu system, which includes sub-menus, this method can be used to
  138.          assign each topic in the menu a unique ID. The method is passed two
  139.          parameters; the item number and the item ID. This ID is of type word,
  140.          and will be returned by the menu method Activate if the item is
  141.          selected by the user. Note that you should not use IDs greater than
  142.          65000, because some of these IDs are used internally by the Toolkit.
  143.  
  144.  
  145.          SetStatus(Item:byte, On:boolean);
  146.  
  147.          Sometimes, certain menu items will not be selectable. For example, a
  148.          File Save option may not be operative until a file has been loaded or
  149.          created. The SetStatus method is used to control whether an option is
  150.          selectable. The method is passed two parameters; the item number and a
  151.          boolean parameter. Set the boolean to TRUE to enable the item and FALSE
  152.          to disable it.
  153.  
  154.  
  155.          SetSubMenu(Item:byte; SubMenu:BaseMenuPtr);
  156.  
  157.          This method is used to indicate that another menu should be displayed,
  158.          if the item is selected by the user. The Toolkit will automatically
  159.          display the new menu below and to the right of the active menu. The
  160.          method is passed two parameters; the item number and the address of the
  161.          sub-menu object. Normally, you will call another menu instance of the
  162.          same type as the parent, e.g. if the parent menu is of type MenuOBJ,
  163.          then the sub-menu is usually of type MenuOBJ. This, however, is not
  164.          mandatory, and any menu item can display a sub-menu of any type in the
  165.          menu object hierarchy. Note that the second parameter is the address of
  166.          the sub-menu, and is normally specified by preceding the menu object
  167.          with the Turbo Pascal "@" address symbol. For example:
  168.  
  169.                      SetSubMenu(5,@FileMenu);
  170.  
  171.  
  172.          When you want to specify all the menu item details, e.g. message, HK,
  173.          sub-menu, etc., you can use the following all-in-one method:
  174.  
  175.  
  176.          AddFullItem(Txt:StrVisible;ID,Hk:word; Msg:StrVisible; SubM:Baseme-
  177.          nuPtr);
  178.  
  179.  
  180.  
  181. 12-4                                                                User's Guide
  182.  
  183. --------------------------------------------------------------------------------
  184.  
  185.          As you may have guessed, this method is used to add a new item and
  186.          specify its settings in one heavy statement! This method is a single
  187.          replacement for five of the previous six methods. The only method that
  188.          is not accommodated by AddFullItem is SetStatus, and the Status is set
  189.          to true by default. Use one of the following values to suppress the
  190.          setting of one or more of the item elements:
  191.  
  192.               No ID                  0
  193.               No hotkey              0
  194.               No message             ''
  195.               No sub-menu            nil
  196.  
  197.          Listed below are two code fragments, both of which define the same
  198.          three-item menu. The first code block uses the individual methods, and
  199.          the second block takes advantage of AddFullItem. It doesn't matter
  200.          which technique you use, so use the one which seems easiest to you.
  201.  
  202.          with MainMenu do
  203.          begin
  204.             Init;
  205.             AddItem(' ~L~oad file ')
  206.             SetID(1,1);
  207.             SetHK(1,76);
  208.             SetMessage(1,'Load a database file from disk');
  209.             AddItem(' ~S~ave file ');
  210.             SetID(2,2);
  211.             SetHK(83);
  212.             SetMessage(2,'Save the current database to disk');
  213.             AddItem(' ~Q~uit ');
  214.             SetID(3,99);
  215.             SetHK(3,81);
  216.             Setmessage(3,'Let''s party!');
  217.             ...
  218.          end;
  219.  
  220.  
  221.          with MainMenu do
  222.          begin
  223.             Init;
  224.             AddFullItem(' ~L~oad file ',1,76,'Load a database file from disk',-
  225.          nil);
  226.             AddFullItem(' ~S~ave file ',2,83,'Save the current database to
  227.          disk',nil);
  228.             AddFullItem(' ~Q~uit ',99,81,'Let''s party!',nil);
  229.             ...
  230.          end;
  231.  
  232.  
  233.          Having created a menu, the following methods can be used to display,
  234.          start, remove and dispose of the menu.
  235.  
  236.  
  237.  
  238. Menus Menus Menus                                                           12-5
  239.  
  240. --------------------------------------------------------------------------------
  241.  
  242.          Draw;
  243.  
  244.          This method instructs the object to draw itself. As soon as the menu is
  245.          drawn, the method returns control back to your program, i.e. the object
  246.          does not process any user input.
  247.  
  248.  
  249.          Activate: word;
  250.  
  251.          This is the main "DO-IT!" method. If the menu is not already visible,
  252.          the menu is drawn, and then the Toolkit processes user input until the
  253.          user selects a menu item or ESCapes (if ESC is enabled). The function
  254.          method returns the ID of the selected item. If the ID was never speci-
  255.          fied, i.e. it is set to zero, the Toolkit will return the actual item
  256.          number. Note, however, that this number is the item number in the
  257.          currently displayed menu. In a system with sub-menus you will not know
  258.          which sub-menu was on display. In a system with sub-menus, you should
  259.          therefore always assign a unique ID to each selectable item. A zero is
  260.          returned if the user escaped.
  261.  
  262.  
  263.          Remove;
  264.  
  265.          This methods removes the menu. If the menu is of type MenuOBJ or Move-
  266.          MenuOBJ, the underlying screen contents are restored. All other menu
  267.          objects do not restore any underlying screen contents -- they simply
  268.          erase the menu text.
  269.  
  270.  
  271.          Done;
  272.  
  273.          When the menu is no longer required, call this method to dispose of the
  274.          memory used internally by the menu.
  275.  
  276.  
  277.  
  278.  
  279. Changing Menu Characteristics
  280.  
  281.          The following methods are used to control the general display charac-
  282.          teristics of the menu:
  283.  
  284.  
  285.          SetGap(G:byte);
  286.  
  287.          This method is used to create a space (or gap) to the left and right of
  288.          each menu item. In a pop-up menu, this can be used to create a space
  289.          between the menu border and the menu text. With Lotus and pull-down
  290.          menus, this method creates a space between each item along the top menu
  291.          bar. The method is passed one parameter; a byte representing the number
  292.          of characters space to allow on either side of each menu item.
  293.  
  294.  
  295.          SetMenuXY(X,Y: byte);
  296.  
  297.  
  298.  
  299. 12-6                                                                User's Guide
  300.  
  301. --------------------------------------------------------------------------------
  302.  
  303.          This method is used to set the specific location of the menu on the
  304.          screen. The method is passed two byte parameters representing the (X,Y)
  305.          coordinate of the top left corner of the menu. With pop-up menus, the
  306.          menu will be centered laterally and vertically if the X or Y parameter
  307.          is set to zero.
  308.  
  309.  
  310.          SetMesssageXY(X,Y:byte);
  311.  
  312.          This method is used to specify the location of the optional message
  313.          which is displayed when a topic is highlighted. The method is passed
  314.          two parameters representing the (X,Y) coordinate of the first character
  315.          in the message.
  316.  
  317.  
  318.          SetAllowEsc(On:boolean);
  319.  
  320.          This method is used to control whether the user may escape from the
  321.          menu. It is passed a single boolean parameter, which should be set to
  322.          TRUE to enable escape (the default), or FALSE to disable it.
  323.  
  324.  
  325.          SetActiveItem(Item:byte);
  326.  
  327.          Normally, the first item in a menu is highlighted when the menu is
  328.          first displayed. If this item is non-selectable, or if you want to
  329.          highlight a different item, use the method SetActiveItem. The method is
  330.          passed one byte parameter identifying the topic number of the item to
  331.          be highlighted.
  332.  
  333.  
  334.          The display colors are controlled by the menu item colors, and (in the
  335.          case of pop-up and pull-down menus) the window display colors. All the
  336.          colors default to values established by LookTOT. To change the look and
  337.          feel of your menus, you should assign new default values to LookTOT.
  338.          Refer to page 3-12 for a description of how to control the LookTOT
  339.          defaults. The following two methods can be used to control the display
  340.          colors of any individual menu:
  341.  
  342.  
  343.          SetColors(HiHot,HoNorm,LoHot,LoNorm,Off:byte);
  344.  
  345.          This method changes the display colors of the individual menu items.
  346.          The procedure is passed five byte parameters: the first two parameters
  347.          control the display color of the menu highlight bar -- the first param-
  348.          eter is the attribute of any highlighted text, e.g. the 'Q' in
  349.          '~Q~uit', and the second parameter is the standard display color, e.g.
  350.          the 'uit' part. The third and fourth parameters are the display attrib-
  351.          utes for the un-selected (or normal) menu items, and the fifth parame-
  352.          ter is the display attribute of inactive items. Note that this method
  353.          automatically sets the window body display color to the parameter
  354.          LoNorm.
  355.  
  356.  
  357.  
  358. Menus Menus Menus                                                           12-7
  359.  
  360. --------------------------------------------------------------------------------
  361.  
  362.          Win^.SetColors(Border,Body,Title,Icons: byte);
  363.  
  364.          In the case of pop-up and pull-down menus, this method sets the colors
  365.          of the underlying window. Refer to page 7-6 for a general description
  366.          of this window method.
  367.  
  368.  
  369.  
  370. Adding Lines and Gaps
  371.  
  372.          Sometimes, you may want to display a menu with some items separated
  373.          from others. By specifying special item text, you instruct the Toolkit
  374.          to draw special lines, or leave a gap. The following item text should
  375.          be used:
  376.  
  377.          ''    A null string creates a gap in the menu.
  378.  
  379.          '-'   A string comprising entirely of the minus sign will result in a
  380.                single horizontal line being drawn from the left to the right of
  381.                the menu.
  382.  
  383.          '='   A string comprising entirely of the equals sign will result in a
  384.                double horizontal line being drawn from the left to the right of
  385.                the menu.
  386.  
  387.          For example, the following code fragment will force a blank line
  388.          between the third and fourth selectable items, and draws a single line
  389.          between the last two picks:
  390.  
  391.                   AddItem('Whips');
  392.                   AddItem('Chains');
  393.                   Additem('Rubber');
  394.                   AddItem('');
  395.                   AddItem('Hard Disks');
  396.                   AddItem('Floppies');
  397.                   AddItem('-');
  398.                   AddItem('Quit');
  399.  
  400.  
  401.  
  402.  
  403.            Note: even non-selectable menu items are recognized as items in
  404.            the menu list. When you use one of the Set methods (described
  405.            earlier), be sure to include the non-selectable items in the list.
  406.            For example, in the above code fragment, the "Quit" item is item
  407.            number 8 (not 6), and its hotkey could be set to "Q" with the
  408.            following method call:
  409.  
  410.                               SetHK(8,ord('Q'));
  411.  
  412.  
  413.  
  414. 12-8                                                                User's Guide
  415.  
  416. --------------------------------------------------------------------------------
  417.  
  418. Examples
  419.  
  420.          Listed below is the demo file DEMMN1.PAS, which illustrates how to
  421.          create a simple menu using some of the methods already described. Fig-
  422.          ure 12.2 illustrates the resultant display.
  423.  
  424.          program DemoMenuOne;
  425.          {DEMMN1 - a basic menu}
  426.  
  427.          USES  DOS, CRT,
  428.                totMENU, totFAST;
  429.  
  430.          var
  431.            Main: MenuOBJ;
  432.            Choice: byte;
  433.          begin
  434.             Screen.Clear(white,'░'); {paint the screen}
  435.             with Main do
  436.             begin
  437.                Init;
  438.                AddItem('');
  439.                AddItem(' Load a file          ');
  440.                AddItem(' Edit Date            ');
  441.                AddItem(' Save the file        ');
  442.                AddItem(' Change configuration ');
  443.                AddItem('-');
  444.                AddItem(' Quit                 ');
  445.                SetStyleTitle(1,' Main Menu ');
  446.                SetActiveItem(2);
  447.                Choice := Activate;
  448.                Done;
  449.             end;
  450.             if Choice = 0 then
  451.                Writeln('You escaped')
  452.             else
  453.                Writeln('You selected menu item ',Choice);
  454.          end.
  455.  
  456.  
  457. Figure 12.2                                                             [SCREEN]
  458. A Simple Menu
  459.  
  460.  
  461.  
  462. Creating Pop-Up Menus
  463.  
  464.          totMENU provides two objects for creating pop-up menus: MenuOBJ and
  465.          MoveMenuOBJ. Both these objects create menus which are displayed in a
  466.          window, the only difference being that MoveMenuOBJ creates moveable
  467.          menus, i.e. menus that the user can drag around the screen.
  468.  
  469.  
  470.  
  471. Menus Menus Menus                                                           12-9
  472.  
  473. --------------------------------------------------------------------------------
  474.  
  475.          Both objects are descendant from BaseMenuOBJ and inherit the following,
  476.          previously described, methods:
  477.  
  478.          Init;
  479.          AddItem(Txt:StrVisible);
  480.          SetHK(Item:byte; HK:word);
  481.          SetMessage(Item:byte; Msg:StrVisible);
  482.          SetID(Item:byte; ID:word);
  483.          SetStatus(Item:byte, On:boolean);
  484.          SetSubMenu(Item:byte; SubMenu:BaseMenuPtr);
  485.          AddFullItem(Txt:StrVisible;ID,Hk:word; Msg:StrVisible; SubM:Baseme-
  486.          nuPtr);
  487.          Draw;
  488.          Activate: word;
  489.          Remove;
  490.          SetGap(G:byte);
  491.          SetMenuXY(X,Y: byte);
  492.          SetMessageXY(X,Y:byte);
  493.          SetAllowEsc(On:boolean);
  494.          SetActiveItem(Item:byte);
  495.          SetColors(HiHot,HoNorm,LoHot,LoNorm,Off:byte);
  496.          Done;
  497.  
  498.  
  499.          The menu is drawn on a window, and the following function methods can
  500.          be used to called any of the window methods:
  501.  
  502.  
  503.          Win: WinPtr;
  504.          Win: MoveWinPtr;
  505.  
  506.          This function returns a pointer to the menu on which the menu is drawn.
  507.          For MenuOBJ instances the method returns a pointer to WinOBJ, and for
  508.          MoveWinOBJ it returns a pointer to MoveWinOBJ. Using the syntax
  509.          Win^.method you may call any of the window methods.
  510.  
  511.  
  512.          The menu window dimensions are automatically calculated from the width
  513.          and number of menu items. You should therefore avoid calling the window
  514.          method SetSize. As a convenience, the following method provides an easy
  515.          way to change the menu style and title.
  516.  
  517.  
  518.          SetStyleTitle(Style:byte; Tit:StrVisible);
  519.  
  520.          This method sets the style and title of the menu window. The style
  521.          parameter is the same as the box style parameter discussed on page 5-7,
  522.          and the title supports the special title characters discussed on page
  523.          5-8.
  524.  
  525.  
  526.  
  527. 12-10                                                               User's Guide
  528.  
  529. --------------------------------------------------------------------------------
  530.  
  531.          The first example shown at the end of the previous section illustrated
  532.          how to create a MenuOBJ menu. The on-disk demo file DEMMN2.PAS shows
  533.          how to create a moveable menu and control the display colors. Listed
  534.          below is the demo file DEMMN3.PAS, which illustrates how to create a
  535.          nested menu system. Figure 12.3 shows the generated menu.
  536.  
  537.          program DemoMenuThree;
  538.          {DEMMN3 - nested pop-up menus}
  539.  
  540.          USES  DOS, CRT,
  541.                totMENU, totFAST, totLOOK, totSYS;
  542.  
  543.          var
  544.            Main,
  545.            Load: MenuOBJ;
  546.            Choice: byte;
  547.  
  548.          begin
  549.             Screen.PartClear(1,1,80,24,white,'░'); {paint the screen}
  550.             Screen.PartClear(1,24,80,25,30,' ');
  551.             with Load do
  552.             begin
  553.                Init;
  554.                AddItem('');
  555.                AddFullItem(' ~1~  Accounts Payable    ',11,49,
  556.                            'Load database ACTP1',nil);
  557.                AddFullItem(' ~2~  Accounts Receivable ',12,50,
  558.                            'Load database ACTR7',nil);
  559.                AddFullItem(' ~3~  Net Assets Employed ',13,51,
  560.                            'Load the ledger file',nil);
  561.                AddFullItem(' ~4~  Net Cash Flow       ',14,52,
  562.                            'Load the cash file',nil);
  563.                SetStyleTitle(6,'Load Menu');
  564.                SetActiveItem(2);
  565.                SetMessageXY(25,25);
  566.                SetGap(1);
  567.                Win^.SetClose(False);
  568.             end;
  569.             with Main do
  570.             begin
  571.                Init;
  572.                AddItem('');
  573.                AddFullItem(' ~1~   Load a file         ',1,49,
  574.                            'Loads a new database file',@Load);
  575.                AddFullItem(' ~2~   Edit Date            ',2,50,
  576.                            'Full screen editing of data base entries',nil);
  577.                AddFullItem(' ~3~   Save the file        ',3,51,
  578.                            'Save database file to disk',nil);
  579.                AddFullItem(' ~4~   Change configuration ',4,52,
  580.                            'Modify colors and defaults',nil);
  581.  
  582.  
  583.  
  584. Menus Menus Menus                                                          12-11
  585.  
  586. --------------------------------------------------------------------------------
  587.  
  588.                AddItem('');
  589.                AddFullItem(' ~Q~   Quit                 ',99,81,
  590.                            'Exit system and return to DOS',nil);
  591.                SetStyleTitle(6,'Main Menu');
  592.                SetActiveItem(2);
  593.                SetMenuXY(0,4);
  594.                SetMessageXY(25,25);
  595.                SetGap(1);
  596.                Win^.SetClose(False);
  597.                Choice := Activate;
  598.                Done;
  599.                Load.Done;
  600.             end;
  601.             if Choice = 0 then
  602.                Writeln('You escaped')
  603.             else
  604.                Writeln('You selected menu item ',Choice);
  605.          end.
  606.  
  607.  
  608. Figure 12.3                                                             [SCREEN]
  609. Nested Pop-Up
  610. Menus
  611.  
  612.  
  613.  
  614. Creating Lotus-style Menus
  615.  
  616.          Lotus-style menus are menu bars which occupy a single line, and the
  617.          user scrolls left and right through the items. An optional description
  618.          of the highlighted item is usually displayed on the line immediately
  619.          below the menu bar.
  620.  
  621.          The LotusMenuOBJ object makes building Lotus-style menus easy. LotusMe-
  622.          nuOBJ is descendant from BaseMenuOBJ, and inherits the following, pre-
  623.          viously described, methods:
  624.  
  625.          Init;
  626.          AddItem(Txt:StrVisible);
  627.          SetHK(Item:byte; HK:word);
  628.          SetMessage(Item:byte; Msg:StrVisible);
  629.          SetID(Item:byte; ID:word);
  630.          SetStatus(Item:byte, On:boolean);
  631.          SetSubMenu(Item:byte; SubMenu:BaseMenuPtr);
  632.          AddFullItem(Txt:StrVisible;ID,Hk:word; Msg:StrVisible; SubM:Baseme-
  633.          nuPtr);
  634.          Draw;
  635.          Activate: word;
  636.          Remove;
  637.          SetGap(G:byte);
  638.          SetMenuXY(X,Y: byte);
  639.  
  640.  
  641. 12-12                                                               User's Guide
  642.  
  643. --------------------------------------------------------------------------------
  644.  
  645.          SetMessageXY(X,Y:byte);
  646.          SetAllowEsc(On:boolean);
  647.          SetActiveItem(Item:byte);
  648.          SetColors(HiHot,HoNorm,LoHot,LoNorm,Off:byte);
  649.          Done;
  650.  
  651.  
  652.          Listed below are the contents of the file DEMMN4.PAS, which uses these
  653.          basic methods to build a simple single-level Lotus menu. Figure 12.4
  654.          shows the resultant menu display.
  655.  
  656.          program DemoMenuFour;
  657.          {DEMMN1 - a simple lotus menu}
  658.  
  659.          USES  DOS, CRT,
  660.                totMENU, totFAST;
  661.  
  662.          var
  663.            P: LotusMenuOBJ;
  664.            Choice: byte;
  665.          begin
  666.             Screen.Clear(white,'░'); {paint the screen}
  667.             with P do
  668.             begin
  669.                Init;
  670.                AddItem('Worksheet');
  671.                AddItem('Range');
  672.                AddItem('Copy');
  673.                AddItem('Move');
  674.                AddItem('File');
  675.                AddItem('Print');
  676.                AddItem('Graph');
  677.                AddItem('Data');
  678.                AddItem('System');
  679.                AddItem('Quit');
  680.                SetActiveItem(1);
  681.                SetGap(1);
  682.                Choice := Activate;
  683.                Done;
  684.             end;
  685.             GotoXY(1,5);
  686.             if Choice = 0 then
  687.                Writeln('You escaped')
  688.             else
  689.                Writeln('You selected menu item ',Choice);
  690.          end.
  691.  
  692.  
  693. Figure 12.4                                                             [SCREEN]
  694. A Simple Lotus
  695. Menu
  696.  
  697.  
  698. Menus Menus Menus                                                          12-13
  699.  
  700. --------------------------------------------------------------------------------
  701.  
  702.          If the user is using a mouse to select an item, the item is selected
  703.          when the user lets go of the mouse button. If the user holds down the
  704.          mouse button, and drifts away from the menu surface, none of the items
  705.          will be highlighted. If the user then releases the mouse button (while
  706.          the mouse cursor is not over the menu surface), a special ID DriftID is
  707.          returned by Activate. DriftID is declared as a constant in the totMENU
  708.          unit. To recap, if the ID 0 is returned, the user escaped, and if
  709.          DriftID is returned, the user drifted off the menu and selected no
  710.          item. All other values indicate that the user chose a specific item
  711.          from the menu.
  712.  
  713.          In addition to the inherited methods, LotusMenuOBJ objects support the
  714.          following methods:
  715.  
  716.  
  717.          SetSpecialKey(HK:word; ID:word);
  718.  
  719.          The hotkeys which are defined for each menu item allow the user to
  720.          select the item by pressing the appropriate hotkey. However, only the
  721.          hotkeys for the currently displayed menu are recognized. In a nested
  722.          menu system, the SetSpecialKey method can be used to define hotkeys
  723.          which will be recognized regardless of which menu level is being dis-
  724.          played. The method is passed two parameters; the keycode of the hotkey
  725.          and the ID which will be returned when the user presses this special
  726.          key. Special hotkeys can be added in any order, and they do not have to
  727.          correspond to any of the actual menu items. For example, you could add
  728.          an [KEYCAP] key to return the value of 1000 with the following state-
  729.          ment:
  730.  
  731.                   SetSpecialKey(301,1000);
  732.  
  733.          If the menu is active, and the user presses [KEYCAP], the menu will
  734.          immediately end and return a value of 1000.
  735.  
  736.  
  737.          Menukey(K:word; X,Y: byte): boolean;
  738.  
  739.          This method is passed three parameters defining the details of a key-
  740.          press, i.e. the keycode, and the (X,Y) coordinate of the mouse when the
  741.          key was pressed. The function method returns TRUE if the key's details
  742.          are recognized by the menu, i.e. if the details represent a menu
  743.          hotkey, or a mouse click on the menu surface.
  744.  
  745.  
  746.          Push(K:word; X,Y: byte);
  747.  
  748.          The Activate method is used to start the menu and wait for user input.
  749.          The Push method is similar to activate, except that the procedure is
  750.          passed the key details for the first input to be processed. This method
  751.          can be used in conjunction with MenuKey to test for a menu key and then
  752.  
  753.  
  754.  
  755. 12-14                                                               User's Guide
  756.  
  757. --------------------------------------------------------------------------------
  758.  
  759.          process it. For example, the following code fragment prompts the user
  760.          for input. If it is related to the menu, the menu is invoked, otherwise
  761.          SomeOtherTask is called:
  762.  
  763.          var
  764.            Lmenu: LotusMenuOBJ;
  765.            K: word;
  766.            X,Y: byte;
  767.            Choice: word;
  768.  
  769.            procedure SetUpLMenu;
  770.            {}
  771.            begin
  772.             with Lmenu do
  773.             begin
  774.                Init;
  775.                {...}
  776.                end;
  777.            end;
  778.  
  779.            procedure SomeOtherTask(K:word;X,Y:byte);
  780.            {}
  781.            begin
  782.               {...}
  783.            end; {SomeOtherTask)}
  784.  
  785.          begin
  786.             Screen.Clear(white,'░'); {paint the screen}
  787.             SetUpLmenu;
  788.             Choice := 0;
  789.             Lmenu.Draw;
  790.             Mouse.Show;
  791.             Repeat
  792.                K := Key.Getkey;
  793.                X := Key.LastX;
  794.                Y := Key.LastY;
  795.                if Lmenu.Menukey(K,X,Y) then
  796.                   Choice := Lmenu.Push(K,X,Y)
  797.                else
  798.                   SomeOtherTask(K,X,Y);
  799.             Until (Choice <> 0) and (Choice <> DriftID);
  800.             Mouse.Hide;
  801.             writeln(Choice);
  802.          end.
  803.  
  804.  
  805.          Lotus menus can be nested many levels deep. Listed below is the demo
  806.          file DEMMN5.PAS, which shows how to create nested menus. Figure 12.5
  807.          shows the resultant display.
  808.  
  809.  
  810.  
  811. Menus Menus Menus                                                          12-15
  812.  
  813. --------------------------------------------------------------------------------
  814.  
  815.          program DemoMenuFive;
  816.          {DEMMN5 - a nested Lotus menu}
  817.  
  818.          USES  DOS, CRT,
  819.                totMENU, totFAST;
  820.  
  821.          var
  822.            Main,
  823.            Worksheet,
  824.            Range: LotusMenuOBJ;
  825.            Choice: word;
  826.  
  827.          procedure Pretend;
  828.          begin
  829.             Screen.Clear(31,' '); {paint the screen}
  830.             Screen.WriteAt(1,4,48,replicate(80,' '));
  831.             Screen.WriteCenter(4,48,'Not 1-2-3!');
  832.             Screen.PartClear(1,5,4,25,48,' ');
  833.          end; {Pretend}
  834.  
  835.          begin
  836.             Pretend;
  837.             with Worksheet do
  838.             begin
  839.                Init;
  840.                AddFullItem('~G~lobal',100,71,'Global stuff',nil);
  841.                AddFullItem('~I~nsert',101,73,'Insert stuff',nil);
  842.                AddFullItem('~D~elete',102,68,'Delete stuff',nil);
  843.                AddFullItem('~C~olumn',103,67,'Column stuff',nil);
  844.                AddFullItem('~E~rase',104,69,'Erase stuff',nil);
  845.                AddFullItem('~T~itles',105,84,'Titles stuff',nil);
  846.                AddFullItem('~W~indow',106,87,'Window stuff',nil);
  847.                AddFullItem('~S~tatus',107,83,'Status stuff',nil);
  848.                AddFullItem('~P~age',108,80,'Page stuff',nil);
  849.                AddFullItem('~H~ide',109,72,'Hide things',nil);
  850.                SetActiveItem(1);
  851.                SetGap(1);
  852.             end;
  853.             with Range do
  854.             begin
  855.                Init;
  856.                AddFullItem('~F~ormat',200,70,'Format stuff',nil);
  857.                AddFullItem('~L~abel',201,76,'Label stuff',nil);
  858.                AddFullItem('~E~rase',202,69,'Erase stuff',nil);
  859.                AddFullItem('~N~ame',203,78,'Name stuff',nil);
  860.                AddFullItem('~J~ustify',204,74,'Justify stuff',nil);
  861.                AddFullItem('~P~rot',205,80,'Protect stuff',nil);
  862.                AddFullItem('~U~nprot',206,85,'Unprotect stuff',nil);
  863.                AddFullItem('~I~nput',207,73,'Input stuff',nil);
  864.                AddFullItem('~V~alue',208,86,'Value stuff',nil);
  865.  
  866.  
  867.  
  868. 12-16                                                               User's Guide
  869.  
  870. --------------------------------------------------------------------------------
  871.  
  872.                AddFullItem('~T~rans',209,84,'Transpose stuff',nil);
  873.                AddFullItem('~S~earch',209,83,'Search for things',nil);
  874.                SetActiveItem(1);
  875.                SetGap(1);
  876.             end;
  877.             with Main do
  878.             begin
  879.                Init;
  880.                AddFullItem('~W~orksheet',1,87,
  881.                            'Worksheet and global operations',@Worksheet);
  882.                AddFullItem('~R~ange',2,82,
  883.                            'Commands for manipulating data ranges',@Range);
  884.                AddFullItem('~C~opy',3,67,
  885.                            'Cell and range copying commands',nil);
  886.                AddFullItem('~M~ove',4,77,'Cell and range moving commands',nil);
  887.                AddFullItem('~F~ile',5,70,'File loading and saving operation-
  888.          s',nil);
  889.                AddFullItem('~P~rint',6,80,'Graph and spreadsheet printing',nil);
  890.                AddFullItem('~G~raph',7,71,'Spreadsheet charting',nil);
  891.                AddFullItem('~D~ata',8,68,'Database operations',nil);
  892.                AddFullItem('~S~ystem',9,83,'Drop to the Operating System',nil);
  893.                AddFullItem('~Q~uit',99,81,'Miller Time!',nil);
  894.                SetActiveItem(1);
  895.                SetGap(1);
  896.                Choice := Activate;
  897.                Done;
  898.                Worksheet.Done;
  899.                Range.Done;
  900.             end;
  901.             gotoxy(1,5);
  902.             if Choice = 0 then
  903.                Writeln('You escaped')
  904.             else
  905.                Writeln('You selected menu item ',Choice);
  906.          end.
  907.  
  908.  
  909.  
  910.  
  911. Figure 12.5                                                             [SCREEN]
  912. Nested Lotus
  913. Menus
  914.  
  915.  
  916.  
  917. Pull Down Menus
  918.  
  919.          The totMENU unit provides a number of objects to help you create pull-
  920.          down menus like the one used in the Turbo Pascal integrated environ-
  921.          ment. The main pull-down menu object is PullMenuOBJ, and it is a
  922.  
  923.  
  924.  
  925. Menus Menus Menus                                                          12-17
  926.  
  927. --------------------------------------------------------------------------------
  928.  
  929.          descendant of LotusMenuOBJ -- a pull-down menu is really a Lotus menu
  930.          which calls pop-up menus when an item is selected from the main menu
  931.          bar. The other pull-down menus are EZPullArrayOBJ and EZPullLinkOBJ,
  932.          which allow you to quickly create a pull-down menu based on the con-
  933.          tents of a string array or linked list, respectively. Hence the prefix,
  934.          EZ!
  935.  
  936.  
  937.  
  938. PullMenuOBJ
  939.  
  940.          99% of Toolkit users will use the EZ objects, but before moving on to
  941.          explain such shortcuts, the PullMenuOBJ object needs to be described in
  942.          detail.
  943.  
  944.          PullMenuOBJ supports the following, previously described, methods:
  945.  
  946.          Init;
  947.          AddItem(Txt:StrVisible);
  948.          SetHK(Item:byte; HK:word);
  949.          SetMessage(Item:byte; Msg:StrVisible);
  950.          SetID(Item:byte; ID:word);
  951.          SetStatus(Item:byte, On:boolean);
  952.          SetSubMenu(Item:byte; SubMenu:BaseMenuPtr);
  953.          AddFullItem(Txt:StrVisible;ID,Hk:word; Msg:StrVisible; SubM:Baseme-
  954.          nuPtr);
  955.          Draw;
  956.          Activate: word;
  957.          Remove;
  958.          SetGap(G:byte);
  959.          SetMenuXY(X,Y: byte);
  960.          SetMessageXY(X,Y:byte);
  961.          SetAllowEsc(On:boolean);
  962.          SetActiveItem(Item:byte);
  963.          SetColors(HiHot,HoNorm,LoHot,LoNorm,Off:byte);
  964.          SetSpecialKey(HK:word; ID:word);
  965.          Menukey(K:word; X,Y: byte): boolean;
  966.          Push(K:word; X,Y: byte);
  967.          Done;
  968.  
  969.  
  970.          To build a pull-down menu using PullMenuOBJ, you create an object of
  971.          type PullMenuOBJ, and one MenuOBJ object for each pull-down menu panel.
  972.          When you add the items to PullMenuOBJ, the sub-menu parameter should be
  973.          a pointer to the appropriate MenuOBJ instance. Listed below is the demo
  974.          program DEMMN6.PAS, followed by figure 12.6 showing the display.
  975.  
  976.          program DemoMenuSix;
  977.          {DEMMN6 - a simple pullmenu}
  978.          USES  DOS, CRT,
  979.                totMENU, totFAST;
  980.  
  981.  
  982.  
  983. 12-18                                                               User's Guide
  984.  
  985. --------------------------------------------------------------------------------
  986.  
  987.          var
  988.            Fmenu,
  989.            Emenu: MenuOBJ;
  990.            Pmenu: PullMenuOBJ;
  991.            Choice: word;
  992.  
  993.          procedure InitSubmenus;
  994.          {}
  995.          begin
  996.             with Fmenu do
  997.             begin
  998.                Init;
  999.                AddFullItem(' ~O~pen...       ',101,79,'',nil);
  1000.                AddFullItem(' ~N~ew           ',102,78,'',nil);
  1001.                AddFullItem(' ~S~ave...       ',103,83,'',nil);
  1002.                AddFullItem(' S~a~ve as       ',104,65,'',nil);
  1003.                AddFullItem(' Save a~l~l      ',105,79,'',nil);
  1004.                AddItem('-');
  1005.                AddFullItem(' ~C~hange dir ...',106,67,'',nil);
  1006.                AddFullItem(' ~P~rint         ',107,80,'',nil);
  1007.                AddFullItem(' ~G~et info...   ',108,71,'',nil);
  1008.                AddFullItem(' ~D~OS shell     ',109,68,'',nil);
  1009.                AddFullItem(' E~x~it          ',110,88,'',nil);
  1010.                SetForPull;
  1011.             end;
  1012.             with Emenu do
  1013.             begin
  1014.                Init;
  1015.                AddFullItem(' ~R~estore line   ',201,82,'',nil);
  1016.                AddItem('-');
  1017.                AddFullItem(' Cu~t~            ',202,84,'',nil);
  1018.                AddFullItem(' ~C~opy           ',203,67,'',nil);
  1019.                AddFullItem(' ~P~aste          ',204,80,'',nil);
  1020.                AddFullItem(' Copy ~E~xample   ',205,69,'',nil);
  1021.                SetStatus(6,false);
  1022.                AddFullItem(' ~S~how clipboard ',206,83,'',nil);
  1023.                AddItem('-');
  1024.                AddFullItem(' C~l~ear          ',207,76,'',nil);
  1025.                SetForPull;
  1026.             end;
  1027.          end; {InitSubMenus}
  1028.  
  1029.          begin
  1030.             Screen.Clear(white,'░'); {paint the screen}
  1031.             Screen.PartClear(1,1,80,1,31,' ');
  1032.             InitSubMenus;
  1033.             with Pmenu do
  1034.             begin
  1035.                Init;
  1036.  
  1037.  
  1038.  
  1039. Menus Menus Menus                                                          12-19
  1040.  
  1041. --------------------------------------------------------------------------------
  1042.  
  1043.                AddFullItem('   ~F~ile   ',1,70,'',@Fmenu);
  1044.                AddFullItem('   ~E~dit   ',2,69,'',@Emenu);
  1045.                AddFullItem('   ~R~un    ',3,82,'',nil);
  1046.                SetID(3,3);
  1047.                Choice := Activate;
  1048.                Done;
  1049.             end;
  1050.             GotoXY(25,15);
  1051.             if Choice = 0 then
  1052.                Writeln('You escaped')
  1053.             else
  1054.                Writeln('You selected menu item ',Choice);
  1055.          end.
  1056.  
  1057.  
  1058.  
  1059.  
  1060. Figure 12.6                                                             [SCREEN]
  1061. A Simple Pull-down
  1062. Menu
  1063.  
  1064.  
  1065.  
  1066.          The demo program creates a pull-down menu with three elements on the
  1067.          menu bar: File, Edit and Run. A sub-menu is displayed when either of
  1068.          the first two items is selected. The program therefore requires three
  1069.          menu objects: a PullMenuOBJ to define the main menu bar, and two
  1070.          MenuOBJ objects to define the pull-down elements. Notice the method
  1071.          call SetForPull in both the MenuOBJ set-up routines. This method sets
  1072.          the characteristics of the MenuOBJ objects to fit in a pull-down menu
  1073.          environment, e.g. the border is set to 1, any titles are removed, etc.
  1074.  
  1075.          Also, notice that each selectable item is assigned a unique ID. When
  1076.          the user chooses an Item (which doesn't call a sub-menu), the item ID
  1077.          is returned by the method Activate or Push.
  1078.  
  1079.          If you want to add more sub-sub-menus, simply create additional MenuOBJ
  1080.          objects, and set a menu item to point to the sub-menu instance. For
  1081.          example, the following code fragment will result in a sub-menu being
  1082.          displayed when the Print option is selected from the file menu (it is
  1083.          assumed that PrintMenu is an instance of MenuOBJ):
  1084.  
  1085.                AddFullItem(' ~P~rint         ',106,80,'',@PrintMenu);
  1086.  
  1087.          As demonstrated by the third item "Run", items on the main menu bar do
  1088.          not have to call sub-menus. If the user selects Run from the main menu,
  1089.          an ID of three is returned.
  1090.  
  1091.  
  1092.  
  1093. 12-20                                                               User's Guide
  1094.  
  1095. --------------------------------------------------------------------------------
  1096.  
  1097. EZ Pull-Down Menus
  1098.  
  1099.          The objects EZPullArrayOBJ and EZPullLinkOBJ provide a quick and easy
  1100.          way of building powerful pull-down menus. The basic principle of the EZ
  1101.          objects is that you define all the components of each menu item in a
  1102.          string, and then instruct the Toolkit to build a pull-down menu from
  1103.          the strings. The strings can either be stored in an array or in a
  1104.          linked list.
  1105.  
  1106.          Each string can have between one and four elements, with each element
  1107.          being separated by a double-quote ("). The first element is the menu
  1108.          item text, the second element is the message or menu description, the
  1109.          third element is the item ID, and the fourth element is an optional
  1110.          special hotkey which can be pressed anywhere in the menu hierarchy to
  1111.          select the item. The syntax of the string is as follows:
  1112.  
  1113.                      'menu text"description"ID"SpecialHK'
  1114.  
  1115.          For example, the following string declares the menu item "Open..." :
  1116.  
  1117.          ' ~O~pen...       "Locate and open a file in an edit window"201"316'
  1118.  
  1119.          You do not need to specify all four elements. For example, if the item
  1120.          does not have a special hotkey, omit the fourth part. If the item text
  1121.          includes a highlighted character, e.g. ~O~, the Toolkit will automati-
  1122.          cally assign that letter as the standard item hotkey.
  1123.  
  1124.          The strings in the array or list must be specified in the order that
  1125.          the picks will appear in the menu, and strings representing a main menu
  1126.          item must begin with the backslash character. If you want a topic to be
  1127.          non-selectable, start the string with an underscore, '_'. For example,
  1128.          the following strings could be used to create a menu similar to the
  1129.          DEMMN6.PAS program described earlier:
  1130.  
  1131.           '\ ~F~ile   ';
  1132.           ' ~O~pen...       "101'
  1133.           ' ~N~ew           "102'
  1134.           ' ~S~ave...       "103'
  1135.           ' S~a~ve as       "104'
  1136.           ' Save a~l~l      "105'
  1137.           '-'
  1138.           ' ~C~hange dir ..."106'
  1139.           ' ~P~rint         "107'
  1140.           ' ~G~et info...   "108'
  1141.           ' ~D~OS shell     "109'
  1142.           ' E~x~it          "110'
  1143.           '\  ~E~dit   '
  1144.           ' ~R~estore line  "201'
  1145.           '-'
  1146.           ' Cu~t~           "202'
  1147.           ' ~C~opy          "203'
  1148.           ' ~P~aste         "204'
  1149.  
  1150.  
  1151.  
  1152. Menus Menus Menus                                                          12-21
  1153.  
  1154. --------------------------------------------------------------------------------
  1155.  
  1156.           '_Copy ~E~xample   "205'
  1157.           ' ~S~how clipboard "206'
  1158.           '-'
  1159.           ' C~l~ear          "207'
  1160.           '\  ~R~un    "3'
  1161.  
  1162.  
  1163.  
  1164.            Note: the EZ objects can only be used to create a single-level
  1165.            pull-down menu. Refer to the section Adding Sub-Menus to see how
  1166.            to customize an EZ pull-down menu with sub-menus.
  1167.  
  1168.  
  1169.          The EZ pull object dynamically creates an instance of PullMenuOBJ, and
  1170.          as many MenuOBJ instances as needed to create the menu. The EZ pull
  1171.          objects include the following two function methods which allow you to
  1172.          directly access the internal PullMenuOBJ and MenuOBJ instances:
  1173.  
  1174.  
  1175.          MainMenu: PullMenuPtr;
  1176.  
  1177.          This function returns a pointer to the PullMenuOBJ instance used by the
  1178.          EZ object. You may change the characteristics settings of the instance
  1179.          by using the syntax Mainmenu^.method. For example, the following method
  1180.          will draw the main menu bar: Mainmenu^.Draw.
  1181.  
  1182.  
  1183.          SubMenu(MenuNumber: byte): SubMenuPtr;
  1184.  
  1185.          This function returns a pointer to one of the MenuOBJ instances, i.e.
  1186.          one of the first-level menu panels. You may change the characteristics
  1187.          of the instance by using the syntax Submenu(num)^.method.
  1188.  
  1189.  
  1190.  
  1191. EZPullArrayOBJ
  1192.  
  1193.          The EZPullArrayOBJ builds and displays a pull-down menu based on the
  1194.          contents of a string array. After calling Init, the following method
  1195.          should be called to pass the menu details to the object:
  1196.  
  1197.  
  1198.          AssignList(var StrArray; Total:longint; StrLength:byte);
  1199.  
  1200.          AssignList identifies the string array which contains the menu struc-
  1201.          ture. The method is passed three parameters; the string array, the
  1202.          total number of elements in the array, and the defined string length of
  1203.          each array element.
  1204.  
  1205.  
  1206.          Unlike other Toolkit objects such as List and Browse, the EZPullArray-
  1207.          OBJ copies the data from the string array. This means that, after
  1208.          assignment, you can dispose of the string array. The partial listing of
  1209.  
  1210.  
  1211.  
  1212.  
  1213. 12-22                                                               User's Guide
  1214.  
  1215. --------------------------------------------------------------------------------
  1216.  
  1217.          the demo file DEMMN7.PAS (listed below), illustrates this technique.
  1218.          The string array is created locally in the procedure CreateMenu, and is
  1219.          automatically disposed of when the CreateMenu procedure finishes.
  1220.  
  1221.          The demo program is a mock-up of Turbo Pascal's own IDE menu (see
  1222.          Figure 12.7)
  1223.  
  1224.          program DemoMenuSeven;
  1225.          {DEMMN7 - using EZPull objects}
  1226.          USES  DOS, CRT,
  1227.                totMENU, totFAST;
  1228.  
  1229.          var
  1230.            Menu: EZPullArrayOBJ;
  1231.            Choice: word;
  1232.  
  1233.          procedure CreateMenu;
  1234.          {}
  1235.          var
  1236.            Mtxt: Array[1..84] of string[90];
  1237.          begin
  1238.             MTxt[1] := '\ p "System Commands';
  1239.             MTxt[2] := ' ~A~bout...  "Show version and copyright information-
  1240.          "100';
  1241.             MTxt[3] := ' ~R~efresh display "Redraw the screen"101';
  1242.             MTxt[4] := ' ~C~lear desktop   "Close all windows on the desktop,
  1243.          clear history lists"102';
  1244.             MTxt[5] := '\ ~F~ile "File management commands (Open, New, Save,
  1245.          etc.)';
  1246.             MTxt[6] := ' ~O~pen...       "Locate and open a file in an edit
  1247.          window"201';
  1248.             {...}
  1249.             MTxt[84] := ' ~H~elp on Help   "How to use online Help"1005';
  1250.             with Menu do
  1251.             begin
  1252.                Init;
  1253.                AssignList(MTxt,84,90);
  1254.             end;
  1255.          end; {CreateMenu}
  1256.  
  1257.          begin
  1258.             Screen.PartClear(1,2,80,24,white,'░'); {paint the screen}
  1259.             Screen.PartClear(1,1,80,1,31,' ');
  1260.             Screen.PartClear(1,25,80,25,31,' ');
  1261.             Screen.WritePlain(9,25,'│');
  1262.             CreateMenu;
  1263.             with Menu do
  1264.             begin
  1265.                Choice := Push(13,0,0);   {Pass Enter to make menu pull down}
  1266.                Done;
  1267.             end;
  1268.  
  1269.  
  1270. Menus Menus Menus                                                          12-23
  1271.  
  1272. --------------------------------------------------------------------------------
  1273.  
  1274.             GotoXY(25,15);
  1275.             if Choice = 0 then
  1276.                Writeln('You escaped')
  1277.             else
  1278.                Writeln('You selected menu item ',Choice);
  1279.          end.
  1280.  
  1281.  
  1282.  
  1283. Figure 12.7                                                             [SCREEN]
  1284. An EZ Pull-down
  1285. Menu
  1286.  
  1287.  
  1288.  
  1289. EZPullLinkOBJ
  1290.  
  1291.          The EZPullLinkOBJ reads the menu definition from a linked list, i.e.
  1292.          from an instance of DLLOBJ or one of its descendants. After calling
  1293.          Init, the following method should be called to pass the menu details to
  1294.          the object:
  1295.  
  1296.  
  1297.          AssignList(var LinkList DLLOBJ);
  1298.  
  1299.          AssignList identifies the linked list which contains the menu defini-
  1300.          tion. The method is passed one parameter; an instance of DLLOBJ or a
  1301.          descendant, e.g. StrDLLOBJ.
  1302.  
  1303.  
  1304.          As with EZPullArrayOBJ, the data is copied from the linked list to the
  1305.          internal menu objects. Listed below is the demo program DEMMN8.PAS,
  1306.          which shows how EZPullLinkOBJ can be used to read a menu from disk.
  1307.  
  1308.          program DemoMenuEight;
  1309.          {DEMMN8 - reading a menu from disk}
  1310.          USES  DOS, CRT,
  1311.                totMENU, totFAST, totLINK;
  1312.  
  1313.          var
  1314.            Menu: EZPullLinkOBJ;
  1315.            Choice: word;
  1316.  
  1317.          procedure CreateMenu;
  1318.          {}
  1319.          var
  1320.            FileList: StrDLLOBJ;
  1321.            Retcode: integer;
  1322.            F: text;
  1323.            Line:string;
  1324.          begin
  1325.             assign(F,'DEMMN8.TXT');
  1326.             {$I-}
  1327.  
  1328.  
  1329.  
  1330.  
  1331. 12-24                                                               User's Guide
  1332.  
  1333. --------------------------------------------------------------------------------
  1334.  
  1335.             reset(F);
  1336.             {$I+}
  1337.             if ioresult <> 0 then
  1338.             begin
  1339.                Writeln('Error: the file DEMMN8.TXT must be in the default
  1340.          directory!');
  1341.                halt(1);
  1342.             end;
  1343.             with FileList do
  1344.             begin
  1345.                Init;
  1346.                Retcode := 0;
  1347.                ReadLn(F,Line);
  1348.                while not eof(F) and (Retcode = 0) do
  1349.                begin
  1350.                   Readln(F,Line);
  1351.                   Retcode := Add(Line);
  1352.                end;
  1353.                close(F);
  1354.             end;
  1355.             with Menu do
  1356.             begin
  1357.                Init;
  1358.                AssignList(FileList);
  1359.                FileList.Done;
  1360.             end;
  1361.          end; {CreateMenu}
  1362.  
  1363.          begin
  1364.             Screen.PartClear(1,2,80,24,white,'░'); {paint the screen}
  1365.             Screen.PartClear(1,1,80,1,31,' ');
  1366.             Screen.PartClear(1,25,80,25,31,' ');
  1367.             Screen.WritePlain(9,25,'│');
  1368.             CreateMenu;
  1369.             with Menu do
  1370.             begin
  1371.                Choice := Push(13,0,0);   {Pass Enter to make menu pull down}
  1372.                Done;
  1373.             end;
  1374.             GotoXY(25,15);
  1375.             if Choice = 0 then
  1376.                Writeln('You escaped')
  1377.             else
  1378.                Writeln('You selected menu item ',Choice);
  1379.          end.
  1380.  
  1381.  
  1382.  
  1383. Menus Menus Menus                                                          12-25
  1384.  
  1385. --------------------------------------------------------------------------------
  1386.  
  1387. Adding Sub-Menus
  1388.  
  1389.          The EZ objects provide a quick way of building a single level pull-down
  1390.          menu. If you want to have some sub-menus, you can still use the EZ
  1391.          objects. First call the AssignList method to create the main pull-down
  1392.          menu objects, and then create as many MenuOBJ instances as needed.
  1393.          Finally, use the SubMenu function method to access individual menu ele-
  1394.          ments and assign your own MenuOBJ instances to the appropriate menu
  1395.          item.
  1396.  
  1397.          Listed below is an extract of the demo file DEMMN9.PAS, which illus-
  1398.          trates this technique:
  1399.  
  1400.          program DemoMenuNine;
  1401.          {DEMMN9 - using a EZPull object with sub menus and hotkeys}
  1402.          USES  DOS, CRT,
  1403.                totMENU, totFAST;
  1404.  
  1405.          var
  1406.            Env,Watch: MenuOBJ;
  1407.            Menu: EZPullArrayOBJ;
  1408.            Choice: word;
  1409.  
  1410.          procedure CreateSubMenus;
  1411.          {}
  1412.          begin
  1413.             with Env do
  1414.             begin
  1415.                Init;
  1416.                SetForPull;
  1417.                AddFullItem(' ~P~references... ',8061,80,
  1418.                            'Specify desktop settings',nil);
  1419.                AddFullItem(' ~E~ditor...      ',8062,69,
  1420.                            'Specify editor settings',nil);
  1421.                AddFullItem(' ~M~ouse...       ',8063,77,
  1422.                            'Specify mouse settings',nil);
  1423.                AddFullItem(' ~S~tartup...     ',8064,83,
  1424.                            'Permanently change default startup options',nil);
  1425.                AddFullItem(' ~C~olors...      ',8065,67,
  1426.                            'Customize IDE colors for windows, menus, etc.',nil);
  1427.             end;
  1428.             with Watch do
  1429.             begin
  1430.                Init;
  1431.                SetForPull;
  1432.                AddFullItem(' ~A~dd watch...       ',7021,65,
  1433.                    'Insert a watch expression into the Watch window',nil);
  1434.                AddFullItem(' ~D~elete watch       ',7022,68,
  1435.                    'Remove the current watch expression from the Watch window',-
  1436.          nil);
  1437.                AddFullItem(' ~E~dit watch...      ',7023,69,
  1438.  
  1439.  
  1440. 12-26                                                               User's Guide
  1441.  
  1442. --------------------------------------------------------------------------------
  1443.  
  1444.                    'Edit the current watch expression in the Watch window',nil);
  1445.                AddFullItem(' ~R~emove all watches ',7024,82,
  1446.                    'Delete all watch expressions from the Watch window',nil);
  1447.             end;
  1448.          end; {CreateSubMenus}
  1449.  
  1450.          procedure CreateMenu;
  1451.          {}
  1452.          var
  1453.            Mtxt: Array[1..84] of string[100];
  1454.          begin
  1455.             MTxt[1] := '\ p "System Commands';
  1456.             {...}
  1457.             MTxt[84] := ' ~H~elp on Help       "How to use online Help"1005';
  1458.             with Menu do
  1459.             begin
  1460.                Init;
  1461.                AssignList(MTxt,84,100);
  1462.             end;
  1463.          end; {CreateMenu}
  1464.  
  1465.          begin
  1466.             Screen.PartClear(1,2,80,24,white,'░'); {paint the screen}
  1467.             Screen.PartClear(1,1,80,1,31,' ');
  1468.             Screen.PartClear(1,25,80,25,31,' ');
  1469.             Screen.WritePlain(9,25,'│');
  1470.             CreateMenu;
  1471.             CreateSubMenus;
  1472.             with Menu do
  1473.             begin
  1474.                SubMenu(7)^.SetSubMenu(2,@Watch);
  1475.                SubMenu(8)^.SetSubMenu(7,@Env);
  1476.                Choice := Activate
  1477.                Done;
  1478.                Env.Done;
  1479.                Watch.Done;
  1480.             end;
  1481.             GotoXY(25,15);
  1482.             if Choice = 0 then
  1483.                Writeln('You escaped')
  1484.             else
  1485.                Writeln('You selected menu item ',Choice);
  1486.          end.
  1487.  
  1488.  
  1489.  
  1490. Figure 12.8                                                             [SCREEN]
  1491. Nested Pull-down
  1492. Menus
  1493.  
  1494.  
  1495.  
  1496. Menus Menus Menus                                                          12-27
  1497.  
  1498. --------------------------------------------------------------------------------
  1499.  
  1500. Adding Help
  1501.  
  1502.          Adding help to menu objects is very similar to the ways described for
  1503.          other objects like DirWinOBJ. To add a help facility to any menu
  1504.          object, all you have to do is create a procedure following some spe-
  1505.          cific rules, and then call the menu method SetHelpHook to instruct the
  1506.          Toolkit to use your procedure.
  1507.  
  1508.          For a procedure to be eligible as a help hook, it must adhere to the
  1509.          following rules:
  1510.  
  1511.          Rule 1     The procedure must be declared as a FAR procedure. This can
  1512.                     be achieved by preceding the procedure with a {$F+} compiler
  1513.                     directive, and following the procedure with a {$F-} direc-
  1514.                     tive. Alternatively, Turbo 6 users can use the new keyword
  1515.                     FAR following the procedure statement.
  1516.  
  1517.          Rule 2     The procedure must be declared with one passed parameter of
  1518.                     type word. This parameter indicates the ID of the high-
  1519.                     lighted item at the time the user requested help.
  1520.  
  1521.          Rule 3     The procedure must be at the root level, i.e. the procedure
  1522.                     cannot be nested within another procedure.
  1523.  
  1524.          The following procedure declaration follows these rules:
  1525.  
  1526.                   {$F+}
  1527.                   procedure MyHelpHook(ID:word);
  1528.                   .....{procedure statements}
  1529.                   end;
  1530.                   {$F-}
  1531.  
  1532.  
  1533.          The following method SetHelpHook is then called to instruct the Toolkit
  1534.          to call your procedure when the user asks for help:
  1535.  
  1536.  
  1537.          SetHelpHook(PassedProc:HelpProc);
  1538.  
  1539.          This method is passed the procedure name of a procedure declared using
  1540.          the rules outlined above.
  1541.  
  1542.  
  1543.          Remember that if you are using an EZ object, you must access the Pull-
  1544.          MenuOBJ using the following statement:
  1545.  
  1546.                   Mainmenu^.SetHelpHook(YourProc);
  1547.  
  1548.