home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / tvision / menuz / menuz.cpp
Encoding:
C/C++ Source or Header  |  1991-10-06  |  10.3 KB  |  259 lines

  1. //========================================================================
  2. //  The following routines have been uploaded to the Borland Forum BPROGB
  3. //  on CompuServe by the Technical Support staff.  They are provided as a
  4. //  courtesy and not as part of a Borland product; and, as such, are
  5. //  provided without the assurance of technical support or any specific
  6. //  guarantees.
  7. //========================================================================
  8. //  Turbo Vision - Building menus
  9. //
  10. //  - This sample code demonstrates a method of creating menus using the
  11. //  an overloaded operator+ to simplify the syntax.
  12. //
  13. //  - A menu is a linked list of TMenuItem, TMenu, and TSubMenu objects.  
  14. //  Normally, the construction of a menu involves one of two techniques.
  15. //  One is nest the constuction of menus inside calls to constuct another
  16. //  menu.  This makes the construction of a menu into one long statement
  17. //  which can be difficult to read and in which it is easy to make a
  18. //  syntax error.  In complex menus, it can also represent one large
  19. //  complex expression that may cause internal compiler tables to be
  20. //  exceeded, resulting in an out of memory error.  The other is to build
  21. //  the menu in reverse order, and pass the pointer to the previous item
  22. //  built as the last parameter (pointer to next menu) to the constructor
  23. //  of the next menu group built.  This forces you to build the menu in
  24. //  reverse order and is not intuitive.
  25. //
  26. //  Another method, is to overload the operator+ for adding two TMenuItem
  27. //  objects.  This makes the menu easier to build.  However, if you use
  28. //  this technique, you may NOT use the TSubMenu class.  Since the
  29. //  operator has been overloaded for TSubMenu + TMenuItem, and TSubMenu is
  30. //  derived from TMenuItem, this could lead to an ambiguity.
  31. //
  32. //  The restriction on using the TSubMenu class is not in the least
  33. //  inconvenient - as this example demonstrates.
  34. //
  35. //  Additional notes:
  36. //  - The reason this works is because of the way menu system is built.
  37. //  Each menu item's next pointer either points to another menu item
  38. //  which is at the same 'level' as that menu item, or it is set to NULL,
  39. //  indicating that it is the last item in that level.  Additionally, each
  40. //  item has an 'action' which is either to case the corresponding cmXXXXX
  41. //  command to be broadcast, or to invoke another menu which will, in
  42. //  turn, consist of a linked list of menu items.  Thus, there is no real
  43. //  difference between the menu items on the 'menu bar' and those listed
  44. //  in one of the sub-menus.  It's just that the top-level list of menu
  45. //  items is displayed across the menu bar, while others, as appear as
  46. //  drop-down menus.
  47. //========================================================================
  48. #define Uses_MsgBox
  49. #define Uses_TApplication
  50. #define Uses_TButton
  51. #define Uses_TDeskTop
  52. #define Uses_TDialog
  53. #define Uses_TKeys
  54. #define Uses_TMenu
  55. #define Uses_TMenuBar
  56. #define Uses_TMenuItem
  57. #define Uses_TStaticText
  58. #define Uses_TStatusDef
  59. #define Uses_TStatusItem
  60. #define Uses_TStatusLine
  61. #define Uses_TSubMenu
  62. #include <tv.h>
  63.  
  64. //========================================================================
  65. //  global data
  66. //------------------------------------------------------------------------
  67. const cmAbout       = 100;
  68. const cmGreet       = 101;
  69. const cmDoIt        = 102;
  70. const cmOne         = 103;
  71. const cmTwo         = 104;
  72. const cmThree       = 105;
  73. const cmSimple      = 106;
  74. const cmRare        = 107;
  75. const cmWell        = 108;
  76. const cmCore        = 109;
  77. const cmRoll        = 110;
  78. const cmCafe        = 111;
  79. const cmTimes       = 112;
  80.  
  81.  
  82. //========================================================================
  83. //  Since the objects will always be in a linked list, and the operator+
  84. //  is processd left-to-right, we will define the function as appending
  85. //  menuItem2 to menuItem1, and then return menuItem1.
  86. //------------------------------------------------------------------------
  87. TMenuItem& operator +( TMenuItem& menuItem1, TMenuItem& menuItem2 )
  88. {
  89.     TMenuItem *p = &menuItem1;
  90.     while( p->next != NULL )
  91.         p = p->next;
  92.     p->next = &menuItem2;
  93.     return menuItem1;
  94. }
  95.  
  96. //========================================================================
  97. //  class definitions
  98. //------------------------------------------------------------------------
  99. class TApp : public TApplication {
  100.     //  main application class
  101.  
  102. public:
  103.     TApp();
  104.  
  105.     // virtual functions to be locally redefined
  106.     static TMenuBar *initMenuBar( TRect r );
  107.     void handleEvent( TEvent &event );
  108.  
  109.     // declare new functions
  110.     void AboutBox();
  111. };
  112.  
  113. //========================================================================
  114. //  implementation of class TApp
  115. //------------------------------------------------------------------------
  116. TApp::TApp() : TProgInit( &TApplication::initStatusLine,
  117.                     &TApp::initMenuBar, &TApplication::initDeskTop )
  118. {
  119. }
  120.  
  121. //------------------------------------------------------------------------
  122. // define menu bar
  123. //------------------------------------------------------------------------
  124. TMenuBar *TApp::initMenuBar( TRect r )
  125. {
  126.     r.b.y = r.a.y + 1;
  127.  
  128.     // for ease of reading, we'll build each item of the top level
  129.     // menu separately, then just add them together in the end
  130.  
  131.     TMenuItem *top1 = new TMenuItem( "~\360~", kbAltSpace, new TMenu(
  132.         // second level pull-down menu
  133.         *new TMenuItem( "~A~bout", cmAbout, kbNoKey, hcNoContext, 0 ) +
  134.         newLine() +
  135.         *new TMenuItem( "~E~xit", kbNoKey, new TMenu(
  136.             // third level pull-down menu
  137.             *new TMenuItem( "~S~ave", cmQuit, kbNoKey, hcNoContext, 0 ) +
  138.             *new TMenuItem( "A~b~andon", cmQuit, kbNoKey, hcNoContext, 0 ) +
  139.             *new TMenuItem( "Just ~Q~uit", cmQuit, kbNoKey, hcNoContext, 0 )
  140.         ) ) +
  141.         *new TMenuItem( "~G~reeting", cmGreet, kbNoKey, hcNoContext, 0 )
  142.     ), hcNoContext );
  143.  
  144.     TMenuItem *top2 = new TMenuItem( "~D~oIt!", cmDoIt, kbAltD, hcNoContext, 0 );
  145.  
  146.     TMenuItem *top3 = new TMenuItem( "~O~ptions", kbAltO, new TMenu(
  147.         // second level pull-down menu
  148.         *new TMenuItem( "Option ~1~", cmOne, kbNoKey, hcNoContext, 0 ) +
  149.         *new TMenuItem( "Option ~2~", cmTwo, kbNoKey, hcNoContext, 0 ) +
  150.         *new TMenuItem( "Option ~3~", cmThree, kbNoKey, hcNoContext, 0 )
  151.     ), hcNoContext );
  152.  
  153.     TMenuItem *top4 = new TMenuItem( "~C~omplex", kbAltC, new TMenu(
  154.         *new TMenuItem( "~S~imple", cmSimple, kbNoKey, hcNoContext, 0 ) +
  155.         *new TMenuItem( "~M~edium", kbNoKey, new TMenu(
  156.             *new TMenuItem( "~R~are", cmRare, kbNoKey, hcNoContext, 0 ) +
  157.             *new TMenuItem( "~W~ell", cmWell, kbNoKey, hcNoContext, 0 )
  158.         ) ) +
  159.         *new TMenuItem( "~H~ard", kbNoKey, new TMenu(
  160.             *new TMenuItem( "~C~ore", cmCore, kbNoKey, hcNoContext, 0 ) +
  161.             *new TMenuItem( "~R~ock", kbNoKey, new TMenu(
  162.                 *new TMenuItem( "&~R~oll", cmRoll, kbNoKey, hcNoContext, 0 ) +
  163.                 *new TMenuItem( "~C~afe", cmCafe, kbNoKey, hcNoContext, 0 )
  164.             ) ) +
  165.             *new TMenuItem( "~T~imes", cmTimes, kbNoKey, hcNoContext, 0 )
  166.         ) )
  167.     ) );
  168.  
  169.     return( new TMenuBar ( r, new TMenu( *top1 + *top2 + *top3 + *top4 ) ) );
  170. }
  171.  
  172.  
  173. //------------------------------------------------------------------------
  174. // event-handler
  175. //------------------------------------------------------------------------
  176. void TApp::handleEvent( TEvent &event )
  177. {
  178.     TApplication::handleEvent( event );
  179.     if( event.what == evCommand )
  180.     {
  181.         switch( event.message.command )
  182.         {
  183.             case cmAbout:       // 'about' box
  184.                 AboutBox();
  185.                 clearEvent( event );
  186.                 break;
  187.             case cmGreet:
  188.                 messageBox( "\003Howdy!", mfInformation | mfOKButton );
  189.                 break;
  190.             case cmDoIt:
  191.                 messageBox( "\003Just do it!", mfInformation | mfOKButton );
  192.                 break;
  193.             case cmOne:
  194.                 messageBox( "\003One", mfInformation | mfOKButton );
  195.                 break;
  196.             case cmTwo:
  197.                 messageBox( "\003Two", mfInformation | mfOKButton );
  198.                 break;
  199.             case cmThree:
  200.                 messageBox( "\003Three", mfInformation | mfOKButton );
  201.                 break;
  202.             case cmSimple:
  203.                 messageBox( "\003Simple!", mfInformation | mfOKButton );
  204.                 break;
  205.             case cmRare:
  206.                 messageBox( "\003Medium Rare", mfInformation | mfOKButton );
  207.                 break;
  208.             case cmWell:
  209.                 messageBox( "\003Medium Well", mfInformation | mfOKButton );
  210.                 break;
  211.             case cmCore:
  212.                 messageBox( "\003Hard Core", mfInformation | mfOKButton );
  213.                 break;
  214.             case cmRoll:
  215.                 messageBox( "\003Hard Rock&Roll", mfInformation | mfOKButton );
  216.                 break;
  217.             case cmCafe:
  218.                 messageBox( "\003Hard Rock Cafe", mfInformation | mfOKButton );
  219.                 break;
  220.             case cmTimes:
  221.                 messageBox( "\003Hard Times", mfInformation | mfOKButton );
  222.                 break;
  223.             default:
  224.                 messageBox( "\003handling error", mfError | mfOKButton );
  225.         }
  226.         clearEvent( event );
  227.     }
  228. }
  229.  
  230. //------------------------------------------------------------------------
  231. // create modal About dialog box
  232. //------------------------------------------------------------------------
  233. void TApp::AboutBox()
  234. {
  235.     // remind us of the purpose of the example
  236.     TDialog *pd = new TDialog( TRect( 0, 0, 35, 12 ), "About" );
  237.     if( pd )
  238.     {
  239.         pd->insert( new TStaticText( TRect( 1, 2, 34, 7 ),
  240.                 "\003Turbo Vision\n\003\n"
  241.                 "\003Simplifying complex menus\n\003\n"
  242.                 "\003Borland Technical Support"));
  243.         pd->insert( new TButton( TRect( 3, 9, 32, 11), "~O~k",
  244.                 cmOK, bfDefault ) );
  245.         pd->options |= ofCentered;
  246.         deskTop->execView( pd );
  247.     }
  248.     destroy( pd );
  249. }
  250.  
  251. //========================================================================
  252. int main( void )
  253. {
  254.     TApp tv6App;
  255.     tv6App.run();
  256.     return 0;
  257. }
  258.  
  259.