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 #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 #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.