PRODUCT  :  Borland C++                           NUMBER  :  1160
  VERSION  :  3.1
       OS  :  DOS
     DATE  :  December 3, 1992                        PAGE  :  1/12

    TITLE  :  Dynamically modifying Turbo Vision menus.




       This document provides source code to an example which
  dynamically modifies menus using Turbo Vision for C++.


  /***********************************************************************
   *                                                                     *
   * MMENU.CPP                                                           *
   *   This module contains the code to support the TMultiMenu class.    *
   *                                                                     *
   ***********************************************************************/

  #define Uses_TEvent
  #define Uses_TMenu
  #define Uses_TSubMenu
  #define Uses_TMenuItem
  #define Uses_TMenuBar
  #include <tv.h>

  #if !defined( __MMENU_H )
  #include "mmenu.h"
  #endif


  /***********************************************************************
   * global operator +
   *
   * Since the objects will always be in a linked list, and the operator+
   * is processd left-to-right, we will define the function as appending
   * menuItem2 to menuItem1, and then return menuItem1.
   ***********************************************************************/

  TMenuItem& operator +( TMenuItem& menuItem1, TMenuItem& menuItem2 )
  {
      TMenuItem *p = &menuItem1;
      while( p->next != NULL )
          p = p->next;
      p->next = &menuItem2;
      return menuItem1;
  }


  /***********************************************************************
   *                                                                     *













  PRODUCT  :  Borland C++                           NUMBER  :  1160
  VERSION  :  3.1
       OS  :  DOS
     DATE  :  December 3, 1992                        PAGE  :  2/12

    TITLE  :  Dynamically modifying Turbo Vision menus.




   * class TTestList                                                     *
   *                                                                     *
   ***********************************************************************
   * TMultiMenu::TMultiMenu
   *   Constructor for a TMultiMenu object.  This version takes an array
   *   of TMenu pointers.
   ***********************************************************************/

  TMultiMenu::TMultiMenu( const TRect& bounds, TMenu *aMenu[],
              int nMenus ) :    TMenuBar( bounds, aMenu[0] ),
              mList( new TMenu *[nMenus] )
  {
      if( nMenus == 0)
          for( nMenus = 0; aMenu[nMenus] != NULL; nMenus++ )
              ;
      numMenus = nMenus;

      for( int i = 0; i < nMenus; i++ )
          mList[i] = aMenu[i];
  }


  /***********************************************************************
   * TMultiMenu::TMultiMenu
   *   Constructor for a TMultiMenu object.  This version takes an array
   *   of TSubMenu objects.
   ***********************************************************************/

  TMultiMenu::TMultiMenu( const TRect& bounds, TSubMenu aMenu[],
                          int nMenus ) :
      TMenuBar( bounds, aMenu[0] ),
      numMenus( nMenus ),
      mList( new TMenu *[nMenus] )
  {
      mList[0] = menu;                  // First menu is already allocated.
      for( int i = 1; i < nMenus; i++ )
          mList[i] = new TMenu( aMenu[i] );
  }


  /***********************************************************************
   * TMultiMenu::~TMultiMenu
   *   Destructor for a TMultiMenu object.  Destroys any stored menus













  PRODUCT  :  Borland C++                           NUMBER  :  1160
  VERSION  :  3.1
       OS  :  DOS
     DATE  :  December 3, 1992                        PAGE  :  3/12

    TITLE  :  Dynamically modifying Turbo Vision menus.




   *   except for the current one (which will be destroyed by ~TMenuBar)
   *   and frees the space where the list was stored.
   ***********************************************************************/

  TMultiMenu::~TMultiMenu()
  {
      for( int i = 0; i < numMenus; i++ )
          if( mList[i] != menu )          // Delete all but current menu.
              delete mList[i];

      delete [] mList;
  }


  /***********************************************************************
   * TMultiMenu::handleEvent
   *   Code to respond to the cmMMChangeMenu broadcast message.  The
   *   data the arrives with this message specifies which menu to switch
   *   to, passed via the infoInt data member of TEvent.
   ***********************************************************************/

  void TMultiMenu::handleEvent( TEvent& event )
  {
      if( event.what == evBroadcast &&
          event.message.command == cmMMChangeMenu )
      {
          if( event.message.infoInt >= 0 &&
              event.message.infoInt < numMenus )
          {
              if( menu != mList[ event.message.infoInt ] )
              {
                  menu = mList[ event.message.infoInt ];
                  drawView();
              }
          }
          clearEvent( event );
      }
      else
          TMenuBar::handleEvent( event );
  }
















  PRODUCT  :  Borland C++                           NUMBER  :  1160
  VERSION  :  3.1
       OS  :  DOS
     DATE  :  December 3, 1992                        PAGE  :  4/12

    TITLE  :  Dynamically modifying Turbo Vision menus.




  /***********************************************************************
   *                                                                     *
   * TEST.CPP                                                            *
   *   This module contains the Turbo Vision application code to run     *
   *   this example.  It sets up the necessary menus to bring up the     *
   *   test module represented by this demo.                             *
   *                                                                     *
   * TEST MODULE for Multiple Menu Bar Demo.                             *
   *                                                                     *
   ***********************************************************************
   *                                                                     *
   * This code was written by Borland Technical Support.                 *
   * It is provided as is with no warranties expressed or implied.       *
   *                                                                     *
   ***********************************************************************/

  #define Uses_TRect
  #define Uses_TKeys
  #define Uses_TEvent
  #define Uses_TDialog
  #define Uses_TMenu
  #define Uses_TMenuItem
  #define Uses_TMenuBar
  #define Uses_TDeskTop
  #define Uses_TProgram
  #define Uses_TApplication
  #include <tv.h>

  #pragma hdrstop

  #if !defined( __CMDS_H )
  #include "cmds.h"
  #endif

  #if !defined( __MMENU_H )
  #include "mmenu.h"
  #endif


  /***********************************************************************
   *
   * Application object for demo.
   *













  PRODUCT  :  Borland C++                           NUMBER  :  1160
  VERSION  :  3.1
       OS  :  DOS
     DATE  :  December 3, 1992                        PAGE  :  5/12

    TITLE  :  Dynamically modifying Turbo Vision menus.




   ***********************************************************************/
  class TTestApp : public TApplication
  {

  public:

      TTestApp();
      static TMenuBar *initMenuBar( TRect r );
      virtual void handleEvent( TEvent& event );

  protected:

      int curMenu;

  };


  /***********************************************************************
   *
   * TTestApp::TTestApp()
   *
   * Application object contructor.
   *
   ***********************************************************************/
  TTestApp::TTestApp() :
      TApplication(),
      TProgInit( initStatusLine, initMenuBar, initDeskTop ),
      curMenu( 0 )
  {
  }


  /***********************************************************************
   *
   * TTestApp::initMenuBar( TRect r )
   *
   * Build several menus and pass them in an array to the TMultiMenu
   * constructor.
   *
   ***********************************************************************/
  TMenuBar *TTestApp::initMenuBar( TRect r )
  {
      r.b.y = r.a.y + 1;













  PRODUCT  :  Borland C++                           NUMBER  :  1160
  VERSION  :  3.1
       OS  :  DOS
     DATE  :  December 3, 1992                        PAGE  :  6/12

    TITLE  :  Dynamically modifying Turbo Vision menus.




      TMenu *M[] =
      {
                      /*  Menu Number One  */
          new TMenu(
            *new TMenuItem( "~N~ext menu", cmCycle, kbAltN ) +
            *new TMenuItem( "~M~enu One", kbAltM, new TMenu(
              *new TMenuItem( "~O~ne", cmOne, kbAltO ) +
              *new TMenuItem( "~T~wo", cmTwo, kbAltT ) +
              *new TMenuItem( "T~h~ree", cmThree, kbAltH )
              )) +
            *new TMenuItem( "~F~ile", kbAltF, new TMenu(
              *new TMenuItem( "~N~ew", cmNothing, kbAltN ) +
              *new TMenuItem( "~O~pen", cmNothing, kbAltO ) +
              *new TMenuItem( "~S~ave", cmNothing, kbAltS ) +
              *new TMenuItem( "S~a~ve all", cmNothing, kbAltA )
              ))
            ),
                      /*  Menu Number Two  */
          new TMenu(
            *new TMenuItem( "~N~ext menu", cmCycle, kbAltN ) +
            *new TMenuItem( "~M~enu Two", kbAltM, new TMenu(
              *new TMenuItem( "~O~ne", cmOne, kbAltO ) +
              *new TMenuItem( "~T~wo", cmTwo, kbAltT ) +
              *new TMenuItem( "T~h~ree", cmThree, kbAltH )
              )) +
            *new TMenuItem( "~E~dit", kbAltE, new TMenu(
              *new TMenuItem( "Cu~t~", cmNothing, kbAltT ) +
              *new TMenuItem( "~C~opy", cmNothing, kbAltC ) +
              *new TMenuItem( "~P~aste", cmNothing, kbAltP )
              ))
            ),
                      /*  Menu Number Three  */
          new TMenu(
            *new TMenuItem( "~N~ext menu", cmCycle, kbAltN ) +
            *new TMenuItem( "~M~enu Three", kbAltM, new TMenu(
              *new TMenuItem( "~O~ne", cmOne, kbAltO ) +
              *new TMenuItem( "~T~wo", cmTwo, kbAltT ) +
              *new TMenuItem( "T~h~ree", cmThree, kbAltH )
              )) +
            *new TMenuItem( "~C~ompile", kbAltC, new TMenu(
              *new TMenuItem( "~C~ompile", cmNothing, kbAltO ) +
              *new TMenuItem( "~M~ake", cmNothing, kbAltT ) +
              *new TMenuItem( "~L~ink", cmNothing, kbAltH ) +













  PRODUCT  :  Borland C++                           NUMBER  :  1160
  VERSION  :  3.1
       OS  :  DOS
     DATE  :  December 3, 1992                        PAGE  :  7/12

    TITLE  :  Dynamically modifying Turbo Vision menus.




              *new TMenuItem( "~B~uild All", cmNothing, kbAltH )
              ))
            ),
                      /*  END of Menu List Marker (NULL)  */
          0
      };
      return new TMultiMenu( r, M );
  }


  /***********************************************************************
   *
   * TTestApp::handleEvent( TEvent& event )
   *
   * Send appropriate messages to the new multi menu object in response
   * to commands generated by the current menu.  The menu bar will switch
   * to a new setting automatically upon receiving the correct message.
   *
   ***********************************************************************/
  void TTestApp::handleEvent( TEvent& event )
  {
      if( event.what == evCommand &&
          event.message.command >= cmOne &&
          event.message.command <= cmThree
        )
      {
          curMenu = (event.message.command - cmOne) % 3;

          message( TProgram::menuBar, evBroadcast, cmMMChangeMenu,
                   (void *) curMenu
                 );
          clearEvent( event );
      }
      else if( event.what == evCommand && event.message.command == cmCycle )
      {
          curMenu = (curMenu + 1) % 3;
          message( TProgram::menuBar, evBroadcast, cmMMChangeMenu,
                   (void *) curMenu
                 );
          clearEvent( event );
      }
      else
          TApplication::handleEvent( event );













  PRODUCT  :  Borland C++                           NUMBER  :  1160
  VERSION  :  3.1
       OS  :  DOS
     DATE  :  December 3, 1992                        PAGE  :  8/12

    TITLE  :  Dynamically modifying Turbo Vision menus.




  }


  /***********************************************************************
   *
   * main()
   *
   ***********************************************************************/
  int main()
  {
      TTestApp TB;
      TB.run();
      return 0;
  }










  /***********************************************************************
   *                                                                     *
   * CMDS.H                                                              *
   *   This header contains various commands used in the main message    *
   *   system (including the menu bar, status line, and miscellaneous    *
   *   dialog boxes.)                                                    *
   *                                                                     *
   * HEADER FILE for Multiple Menu Bar Demo                              *
   *                                                                     *
   ***********************************************************************
   *                                                                     *
   * This code was written by Borland Technical Support.                 *
   * It is provided as is with no warranties expressed or implied.       *
   *                                                                     *
   ***********************************************************************/

  #ifndef _CMDS_H
  #define _CMDS_H














  PRODUCT  :  Borland C++                           NUMBER  :  1160
  VERSION  :  3.1
       OS  :  DOS
     DATE  :  December 3, 1992                        PAGE  :  9/12

    TITLE  :  Dynamically modifying Turbo Vision menus.




  const unsigned cmOne     = 100;
  const unsigned cmTwo     = 101;
  const unsigned cmThree   = 102;
  const unsigned cmCycle   = 110;
  const unsigned cmNothing = 111;

  #endif










  /***********************************************************************
   *                                                                     *
   * MMENU.H                                                             *
   *   This module contains the class definitions for the MMENU.CPP      *
   *   source module.                                                    *
   *                                                                     *
   * Classes:                                                            *
   *   TMultiMenu         New object derived from TMenuBar to support    *
   *                      dynamic changing of menus.                     *
   *                                                                     *
   *   TMenuItem& operator+( TMenuItem& one, TMenuItem& two )            *
   *                      Operator that links two TMenuItems together    *
   *                                                                     *
   ***********************************************************************
   *                                                                     *
   * This code was written by Borland Technical Support.                 *
   * It is provided as is with no warranties expressed or implied.       *
   *                                                                     *
   ***********************************************************************/

  /*
   * class TMultiMenu - A new menubar that supports dynamic changing of menus
   *   via the messaging system.
   *
   * When the TMultiMenu object is created, an array of TMenu or TSubMenu
   * objects is passed to the constructor.  At runtime, any of these menus can













  PRODUCT  :  Borland C++                           NUMBER  :  1160
  VERSION  :  3.1
       OS  :  DOS
     DATE  :  December 3, 1992                       PAGE  :  10/12

    TITLE  :  Dynamically modifying Turbo Vision menus.




   * be selected by sending a broadcast message to the menubar.  The following
   * parameters for the message function should be used for this object.
   *
   * message( TView *receiver, ushort what, ushort command, void *infoPtr )
   *
   *   receiver = pointer to menubar object or its owner.  The system menubar
   *     is accessible via the static variable TProgram::menubar.
   *
   *   what = evBroadcast.
   *
   *   command =
   *     cmMMChangeMenu : This command selects the menu whose number was
   *       passed in the infoPtr member.  This number is an unsigned integer.
   *
   *   infoPtr = Depends on command issued.  See particular command for
   *     details
   *
   * Example:
   *
   *   message( TProgram::menubar, evBroadcast, cmMMChangeMenu, (void *) 3 )
   *
   * This example would select menu number 3 for the system menubar.  If
   * there are not three menus, the message is ignored and the menu is
   * unchanged.
   *
   * The TMultiMenu constructors are very similar to the TMenuBar constructors
   * except that instead of taking a single TMenu pointer or a single TSubMenu
   * reference, they take an array of either of these.  (See below.)  When
   * using the form that takes a TMenu *[], the last member of the array
   * should be a NULL when taking advantage of the default argument for the
   * third parameter which represents the number of menus supported.
   *
   * The last component of this file is an overloaded operator that can
   * link two TMenuItem objects together.  This operator has been used to
   * make the example code in the test module much easier to read.
   */

  class TMultiMenu : public TMenuBar
  {

  public:

      TMultiMenu( const TRect& bounds, TMenu *aMenu[], int nMenus = 0 );













  PRODUCT  :  Borland C++                           NUMBER  :  1160
  VERSION  :  3.1
       OS  :  DOS
     DATE  :  December 3, 1992                       PAGE  :  11/12

    TITLE  :  Dynamically modifying Turbo Vision menus.




      TMultiMenu( const TRect& bounds, TSubMenu aMenu[], int nMenus );
      ~TMultiMenu();

      virtual void handleEvent( TEvent& event );

  protected:

      TMenu **mList;
      int numMenus;

  };

  const unsigned cmMMChangeMenu = 0x1600;

  TMenuItem& operator +( TMenuItem& menu1, TMenuItem& menu2 );









  #
  # Makefile for Turbo Vision demo applications
  #
  # Written by Borland Tech Support, 1992.
  #
  .AUTODEPEND

  INCDIR = c:\borlandc\include;c:\borlandc\tvision\include
  LIBDIR = c:\borlandc\lib;c:\borlandc\tvision\lib

  NAME = mmenu
  OBJS = test.obj $(NAME).obj

  CFLAGS = -c -ml -O2 -I$(INCDIR) -L$(LIBDIR)


  .cpp.obj:
      bcc +$(NAME).cfg {$*.cpp }














  PRODUCT  :  Borland C++                           NUMBER  :  1160
  VERSION  :  3.1
       OS  :  DOS
     DATE  :  December 3, 1992                       PAGE  :  12/12

    TITLE  :  Dynamically modifying Turbo Vision menus.




  # MMENU.EXE

  $(NAME).exe: $(NAME).cfg $(OBJS)
      tlink @&&~
  /c /x /L$(LIBDIR) c0l.obj + $(OBJS)
  $(NAME).exe
  $(NAME).map
  tv.lib + cl.lib
  ~


  # MMENU.CFG

  $(NAME).cfg: makefile
      copy &&~
  $(CFLAGS)
  ~ $(NAME).cfg






  DISCLAIMER: You have the right to use this technical information subject to
  the terms of the No-Nonsense License Statement that you received with the
  Borland product to which this information pertains.