home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / xbase / library / clipper / patches / menu.prg < prev    next >
Encoding:
Text File  |  1991-01-28  |  17.0 KB  |  502 lines

  1. /*
  2.  AUTHOR.....:ELMER O. LAUDENSLAGER, III
  3.  PROGRAM....:MENU.PRG
  4.  DATE.......:NOVEMBER 25, 1990
  5.  PURPOSE....:CREATE PULL DOWN MENU BAR TYPE OF MENU STRUCTURE
  6.  MODIFIED...:01/28/91
  7.    WHY......:ADDED MUCHO COMMENTS TO THIS FILE WHILE THE PROGRAM IS
  8.             :STILL FRESH IN MY MIND.  ALSO, SUBMISSION TO PC MAGAZINE
  9.             :WILL BE IN THE MAIL SHORTLY. (AS WELL AS TO NANTUCKET)
  10.  
  11.  This is my method of creating pull down menus for use in Nantucket's
  12.  Clipper 5.0  Note: these routines will not work with Clipper '87 or
  13.  previous versions of Clipper or with dBASE III + without the extensive
  14.  modification of this code. Do not delete the #INCLUDE 'Box.ch'
  15.  line or this procedure will not compile!
  16.  
  17.  This is a brief description of what happens and how it works.  When the
  18.  program starts, it sets up the color scheme that I like to use.  You may
  19.  edit it to your satisfaction.  The first thing I do is draw the title with
  20.  the draw_title() procedure.  This can be your client's company logo if you
  21.  like.  It can be a complex, or as simple as you choose.  The next thing
  22.  that happens is that the menus are initialized with the init_menus()
  23.  procedure.  In the menu initialization procedures, the top bar, is created,
  24.  the coordinates of all pull down boxes are created, and the x,y coordinates
  25.  are obtained.
  26.  
  27.  All this program does is create a large DO WHILE..ENDDO with an EXIT out
  28.  of the endless loop.  A complex case structure is processed from the
  29.  information obtained from the use of a PROMPT statement and an ACHOICE call.
  30.  The menu bar utilizes the PROMPT statement and the pull down menus uses the
  31.  ACHOICE function.  The reason for using the ACHOICE function for the pull
  32.  down menus is for the case that I have many selections under 1 heading.
  33.  (It's possible, but not probable.)
  34.  
  35.  When the target is found, another procedure is called executing routines
  36.  from that choice.  It may look complex (and it was an interesting application
  37.  of brain power), it is functional!!!
  38.  
  39.  Why did I go to the trouble of creating this??? Well, I was getting bored
  40.  with the simple up/down processing of menus.  Also, the world is going
  41.  GUI (Graphical User Interface) and this is my (albeit pitiful) attempt to
  42.  bring some of that kind of functionality to my customers programs.
  43.  
  44.  This code is functional.  This code works as it is contained herein.
  45.  
  46. */
  47.  
  48. #INCLUDE 'Box.ch'
  49. SET CURSOR OFF
  50. SET CONFIRM OFF
  51. SET SCOREBOARD OFF
  52. SET BELL OFF
  53. SET WRAP ON
  54. PUBLIC normal, inverse, intense, black_white
  55. PUBLIC flash_intense, get_color, save_main_area
  56. if iscolor()
  57.    normal = 'w/b,b/w,,b,+w/b'
  58.    inverse = 'b/w'
  59.    intense = '+w/b,b/w,,b,+w/b'
  60.    flash_intense = '*+w/b,b/w,,b,*+w/b'
  61.    black_white = 'w/n,n/w,,n,+w/n'
  62.    get_color = 'W/B,GR+/N'
  63. else
  64.    normal = 'w/n,n/w,,n,+w/n'
  65.    inverse = 'n/w'
  66.    intense = '+w/n,n/w,,n,+w/n'
  67.    flash_intense = '*+w/n,n/w,,n,*+w/n'
  68.    black_white = 'w/n,n/w,,n,+w/n'
  69.    get_color = '+w/n,n/w,,n,+w/n'
  70. endif
  71.  
  72. draw_title()
  73. init_menus()
  74. main_ans = 1
  75.  
  76. DO WHILE .T.
  77.    SETCOLOR(normal)
  78.    main_ans = Menu_Bar(main_ans)            //Get the left & right choice
  79.    sub_ans  = Choice(main_ans)              //Get the up & down choice
  80.    sub_ans_process( sub_ans, @main_ans)     //Process the answers
  81.    save_main_area = savescreen(00,00,24,79) //Save the entire screen
  82.    if sub_ans <= 0                          //sub_ans will be <= 0 for
  83.       loop                                  //the left or right arrow in
  84.    endif                                    //or the ESC key from the
  85.    do case                                  //processing of information from
  86.                                             //the ACHOICE entries
  87.  
  88.       case main_ans = 0 .or. main_ans = len(menu_names)+1 // the quit array
  89.       if sub_ans = 1
  90.          exit
  91.       endif
  92.  
  93.       case main_ans = 1
  94.       do case
  95.          case sub_ans = 1
  96.             //help() // call your help routines here
  97.             keyboard chr(13)
  98.       end case
  99.  
  100. /*
  101.  This is the first pull down menu selection.  What you do is have a
  102.  procedure here that will get called when the selection is chosen.  If
  103.  you refer to the init_menus() procedure, you will note that there are
  104.  three choices in the menu_1 array.  They coorespond to sub_ans 1 thru
  105.  sub_ans 3.  The same holds true for all of the other choices in the
  106.  top bar.  There is a corresponding case (main_ans) for each choice
  107.  across the top for each of the sub_ans gotten.  That's all there is to it!
  108. */
  109.  
  110.       case main_ans = 2
  111.       do case
  112.          case sub_ans = 1
  113.             //proc() 1 here
  114.          case sub_ans = 2
  115.             //proc() 2 here
  116.          case sub_ans = 3
  117.             //proc() 3 here
  118.       end case
  119.       keyboard chr(13)
  120.  
  121.       case main_ans = 3
  122.       do case
  123.          case sub_ans = 1
  124.  
  125.          case sub_ans = 2
  126.  
  127.          case sub_ans = 3
  128.  
  129.          case sub_ans = 4
  130.  
  131.          case sub_ans = 5
  132.  
  133.          case sub_ans = 6
  134.  
  135.       end case
  136.       keyboard chr(13)
  137.  
  138.       case main_ans = 4
  139.       do case
  140.          case sub_ans = 1
  141.  
  142.          case sub_ans = 2
  143.  
  144.       end case
  145.       keyboard chr(13)
  146.  
  147.       case main_ans = 5
  148.       do case
  149.          case sub_ans = 1
  150.  
  151.          case sub_ans = 2
  152.  
  153.       end case
  154.       keyboard chr(13)
  155.  
  156.       case main_ans = 6
  157.       do case
  158.          case sub_ans = 1
  159.  
  160.          case sub_ans = 2
  161.  
  162.       end case
  163.       keyboard chr(13)
  164.  
  165.    end case
  166.    restscreen(00,00,24,79,save_main_area)
  167. ENDDO
  168.  
  169. SETCOLOR(BLACK_WHITE)
  170. CLEAR SCREEN
  171. SET CURSOR ON
  172. RETURN
  173.  
  174. /*
  175.  Whew!  If you have gotten thru this whole program and understand what I am
  176.  trying to accomplish, Have one on me!!
  177.  Elmer O. Laudenslager, III
  178. */
  179.  
  180.  
  181. ***************************************
  182. * Procedures necessary for pull down  *
  183. * menus.                              *
  184. ***************************************
  185.  
  186. ***************************************
  187. procedure init_menus()
  188. ***************************************
  189. local x,y,z
  190.  
  191. /*
  192.  The public statements below define zero length arrays to the menu_names
  193.  array, the menu_X thru menu_X arrays, and the pos_X thru pos_X arrays.
  194.  There must be 1 array in the form of menu_1 thru menu_X for each element
  195.  in the menu_names array.  The same is true for the pos array.
  196. */
  197.  
  198. public menu_names[0]                             //array of menu names
  199. public menu_1[0], menu_2[0], menu_3[0]           //arrays containing menu choices
  200. public menu_4[0], menu_5[0], menu_6[0]
  201. public pos_1[4], pos_2[4],pos_3[4],pos_quit[4]   //arrays containing coordinates for each pull down menu
  202. public pos_4[4], pos_5[4],pos_6[4]
  203. public quit[1]                                   //define quit array
  204. quit[1] = ' Exit the Application '               //give quit element 1 a value
  205. public top_menu                                  //public top_menu
  206. top_menu = ''
  207. // initialize all menu arrays.  make sure that there is 1 menu_name entry
  208. // for each menu listed above.
  209.  
  210. aadd(menu_names,' Help ')    //initialize menu names array
  211. aadd(menu_names,' First ')   //be sure that each name has a space
  212. aadd(menu_names,' Second ')  //at both the beginning and end
  213. aadd(menu_names,' Third ')   //for proper menuing spacing.
  214. aadd(menu_names,' 4th ')     //If you keep each menu title unique,
  215. aadd(menu_names,' 5th ')     //you can then use the first letter to select.
  216. aadd(menu_1,'Help Index')            //initialize menu_1 choices
  217. aadd(menu_2,'First')                 //initialize menu_2
  218. aadd(menu_2,'Second')
  219. aadd(menu_2,'Third')
  220. aadd(menu_3,'1st Item')              //initialize menu_3
  221. aadd(menu_3,'2nd Item')
  222. aadd(menu_3,'3rd Item')
  223. aadd(menu_3,'4th Item')
  224. aadd(menu_3,'5th Item')
  225. aadd(menu_3,'6th Item')
  226. aadd(menu_4,'First Item in Menu 4')  //initialize menu_4
  227. aadd(menu_4,'Second Item in Menu 4')
  228. aadd(menu_5,'1st in 5')              //initialize menu_5
  229. aadd(menu_5,'2nd in 5')
  230. aadd(menu_6,'first in 6')            //initialize menu_6
  231. aadd(menu_6,'first in 7')
  232.  
  233. for x = 1 to len(menu_names)           //create the top_menu value out of
  234.    top_menu = top_menu + menu_names[x] //the menu_names array. Be sure that
  235. next                                   //watch the size of your names.  You
  236.                                        //only have 73 characters.  See below.
  237.  
  238. y = left(top_menu+space(73),73)
  239. top_menu = y + 'Quit'                  //add the Quit to the top_menu, note,
  240.                                        //top_menu will be truncated to 73
  241.                                        //characters
  242.  
  243. /*
  244.  Define positions of upper left corner.  If you want to move the menu
  245.  down a couple of lines, change the top line to be different than 2.
  246. */
  247.  
  248. pos_1[1] = 2
  249. pos_2[1] = 2
  250. pos_3[1] = 2
  251. pos_4[1] = 2
  252. pos_5[1] = 2
  253. pos_6[1] = 2
  254.  
  255. /*
  256.  The code in this next block will define the starting position across the
  257.  top of the menu bar for the box.  Note:  if you get too close to the right
  258.  side of the screen, you should check into how the Quit box coordinates are
  259.  handled.
  260. */
  261.  
  262. pos_1[2] = centr(top_menu)
  263. pos_2[2] = centr(top_menu) + len(menu_names[1])
  264. pos_3[2] = centr(top_menu) + len(menu_names[1]) + len(menu_names[2])
  265. pos_4[2] = centr(top_menu) + len(menu_names[1]) + len(menu_names[2]) + len(menu_names[3])
  266. pos_5[2] = centr(top_menu) + len(menu_names[1]) + len(menu_names[2]) + len(menu_names[3]) + len(menu_names[4])
  267. pos_6[2] = centr(top_menu) + len(menu_names[1]) + len(menu_names[2]) + len(menu_names[3]) + len(menu_names[4]) + len(menu_names[5])
  268.  
  269. /*
  270.  This next block gets the length of the menu choices array.  If the number
  271.  of options in a menu is greater than 7, then the ACHOICE function will
  272.  handle scrolling of the options in the pull down box.  You can change the
  273.  bottom line (10) to a higher or lower limit but be aware that you must
  274.  also change the value of 7 up and down by the same amount that you change
  275.  the value of 10.
  276. */
  277.  
  278. pos_1[3] = iif(len(menu_1) > 7,10,len(menu_1)+3)
  279. pos_2[3] = iif(len(menu_2) > 7,10,len(menu_2)+3)
  280. pos_3[3] = iif(len(menu_3) > 7,10,len(menu_3)+3)
  281. pos_4[3] = iif(len(menu_4) > 7,10,len(menu_4)+3)
  282. pos_5[3] = iif(len(menu_5) > 7,10,len(menu_5)+3)
  283. pos_6[3] = iif(len(menu_6) > 7,10,len(menu_6)+3)
  284.  
  285. /*
  286.  And finally, the fourth coordinate that is necessary for the ACHOICE as well
  287.  as other functions is obtained.
  288. */
  289.  
  290. z = 0
  291. for x = 1 to len(menu_1)
  292.    if z < len(menu_1[x])
  293.       z = len(menu_1[x])
  294.    endif
  295. next
  296. pos_1[4] = z + pos_1[2] + 1
  297.  
  298. z = 0
  299. for x = 1 to len(menu_2)
  300.    if z < len(menu_2[x])
  301.       z = len(menu_2[x])
  302.    endif
  303. next
  304. pos_2[4] = z + pos_2[2] + 1
  305.  
  306. z = 0
  307. for x = 1 to len(menu_3)
  308.    if z < len(menu_3[x])
  309.       z = len(menu_3[x])
  310.    endif
  311. next
  312. pos_3[4] = z + pos_3[2] + 1
  313.  
  314. z = 0
  315. for x = 1 to len(menu_4)
  316.    if z < len(menu_4[x])
  317.       z = len(menu_4[x])
  318.    endif
  319. next
  320. pos_4[4] = z + pos_4[2] + 1
  321.  
  322. z = 0
  323. for x = 1 to len(menu_5)
  324.    if z < len(menu_5[x])
  325.       z = len(menu_5[x])
  326.    endif
  327. next
  328. pos_5[4] = z + pos_5[2] + 1
  329.  
  330. z = 0
  331. for x = 1 to len(menu_6)
  332.    if z < len(menu_6[x])
  333.       z = len(menu_6[x])
  334.    endif
  335. next
  336. pos_6[4] = z + pos_6[2] + 1
  337.  
  338. // A note on positioning.  If the number of options across the menu bar
  339. // becomes too numerous or lengthy, you may have to adopt the "Quit"
  340. // sequence for the menu positioning.
  341.  
  342. // position the Quit array.  will always be here
  343.  
  344. pos_quit[2] = 78 - (len(quit[1]) + 1)
  345. pos_quit[1] = 2
  346. pos_quit[4] = 78
  347. pos_quit[3] = iif(len(quit) > 7,10,len(quit)+3)
  348. return
  349.  
  350. ***************************************
  351. function Menu_Bar( mch )
  352. ***************************************
  353. local _main_choice
  354. _main_choice = mch
  355. @ 00,00,02,79 box B_DOUBLE
  356. @ 01,centr(top_menu) say top_menu
  357.    set message to 22 center
  358.    @ 01, centr(top_menu) PROMPT menu_names[1] message '' //Prompt for the first menu choice.  \
  359.    @ 01, col()           PROMPT menu_names[2] message '' //Prompt for menu 2.                  | Note, all of the messages
  360.    @ 01, col()           PROMPT menu_names[3] message '' //Prompt for menu 3.                  | must be the same size.
  361.    @ 01, col()           PROMPT menu_names[4] message '' //Prompt for menu 4.                  | If they are not, you will
  362.    @ 01, col()           PROMPT menu_names[5] message '' //Prompt for menu 5.                  | have smaller ones over-
  363.    @ 01, col()           PROMPT menu_names[6] message '' //Prompt for menu 6.             | lapping portions of the
  364.    @ 01, 73              PROMPT ' Quit '      message '' //Prompt for the exit.               /  longer ones.
  365.  
  366.    menu to _main_choice                           //Get menu choice
  367.  
  368. return _main_choice
  369.  
  370. ***************************************
  371. function choice( _main_choice )
  372. ***************************************
  373. local choice, scr_save
  374. //
  375. // a case statement will bee needed for each of the options across the
  376. // menu bar. you will have to manually add or delete a case as necessary.
  377. //
  378.  
  379. //
  380. // what is happening on each of the items in the case is that the box
  381. // area is first saved.  next the box "B_DOUBLE_SINGLE" is drawn,
  382. // then the achoice function is called. finally, the saved area is
  383. // restored.
  384. //
  385. do case
  386.    case _main_choice = len(menu_names) + 1 .or. _main_choice = 0
  387.       scr_save = savescreen(pos_quit[1],pos_quit[2],pos_quit[3],pos_quit[4])
  388.       @ pos_quit[1], pos_quit[2], pos_quit[3], pos_quit[4] box B_DOUBLE_SINGLE
  389.       choice = achoice(pos_quit[1]+1, pos_quit[2]+1, pos_quit[3]-1,pos_quit[4]-1,quit)
  390.       restscreen(pos_quit[1],pos_quit[2],pos_quit[3],pos_quit[4],scr_save)
  391.  
  392.    case _main_choice = 1
  393.       scr_save = savescreen(pos_1[1],pos_1[2],pos_1[3],pos_1[4])
  394.       @ pos_1[1], pos_1[2], pos_1[3], pos_1[4] box B_DOUBLE_SINGLE
  395.       choice = achoice(pos_1[1]+1, pos_1[2]+1, pos_1[3]-1,pos_1[4]-1,menu_1)
  396.       restscreen(pos_1[1],pos_1[2],pos_1[3],pos_1[4],scr_save)
  397.  
  398.    case _main_choice = 2
  399.       scr_save = savescreen(pos_2[1],pos_2[2],pos_2[3],pos_2[4])
  400.       @ pos_2[1], pos_2[2], pos_2[3], pos_2[4] box B_DOUBLE_SINGLE
  401.       choice = achoice(pos_2[1]+1, pos_2[2]+1, pos_2[3]-1,pos_2[4]-1,menu_2)
  402.       restscreen(pos_2[1],pos_2[2],pos_2[3],pos_2[4],scr_save)
  403.  
  404.    case _main_choice = 3
  405.       scr_save = savescreen(pos_3[1],pos_3[2],pos_3[3],pos_3[4])
  406.       @ pos_3[1], pos_3[2], pos_3[3], pos_3[4] box B_DOUBLE_SINGLE
  407.       choice = achoice(pos_3[1]+1, pos_3[2]+1, pos_3[3]-1,pos_3[4]-1,menu_3)
  408.       restscreen(pos_3[1],pos_3[2],pos_3[3],pos_3[4],scr_save)
  409.  
  410.    case _main_choice = 4
  411.       scr_save = savescreen(pos_4[1],pos_4[2],pos_4[3],pos_4[4])
  412.       @ pos_4[1], pos_4[2], pos_4[3], pos_4[4] box B_DOUBLE_SINGLE
  413.       choice = achoice(pos_4[1]+1, pos_4[2]+1, pos_4[3]-1,pos_4[4]-1,menu_4)
  414.       restscreen(pos_4[1],pos_4[2],pos_4[3],pos_4[4],scr_save)
  415.  
  416.    case _main_choice = 5
  417.       scr_save = savescreen(pos_5[1],pos_5[2],pos_5[3],pos_5[4])
  418.       @ pos_5[1], pos_5[2], pos_5[3], pos_5[4] box B_DOUBLE_SINGLE
  419.       choice = achoice(pos_5[1]+1, pos_5[2]+1, pos_5[3]-1,pos_5[4]-1,menu_5)
  420.       restscreen(pos_5[1],pos_5[2],pos_5[3],pos_5[4],scr_save)
  421.  
  422.    case _main_choice = 6
  423.       scr_save = savescreen(pos_6[1],pos_6[2],pos_6[3],pos_6[4])
  424.       @ pos_6[1], pos_6[2], pos_6[3], pos_6[4] box B_DOUBLE_SINGLE
  425.       choice = achoice(pos_6[1]+1, pos_6[2]+1, pos_6[3]-1,pos_6[4]-1,menu_6)
  426.       restscreen(pos_6[1],pos_6[2],pos_6[3],pos_6[4],scr_save)
  427. end case
  428.  
  429. //
  430. // should the user press the left or right arrow or the esc key, the
  431. // case statement below will either return a -1 or -2 for arrow key,
  432. // 0 for the esc key, or the actual choice.
  433. //
  434.  
  435. do case
  436.    case lastkey() = 19
  437.       return -1
  438.  
  439.    case lastkey() = 4
  440.       return -2
  441.  
  442.    case lastkey() = 27
  443.       return 0
  444.  
  445.    otherwise
  446.       return choice
  447. end case
  448. return
  449.  
  450. ***********************
  451. procedure draw_title( )
  452. ***********************
  453.    SETCOLOR(normal)
  454.    CLEAR SCREEN
  455.    @ 10, 00 SAY '═══════════════════════════════════════════════════════════════════════════════'
  456.    @ 14, 00 SAY '───────────────────────────────────────────────────────────────────────────────'
  457.    @ 00,00,02,79 BOX B_DOUBLE
  458.    msg = 'Y O U R   C O M P A N Y   N A M E   H E R E'
  459.    setcolor(intense)
  460.    @ 12, CENTR(msg) SAY msg
  461.    msg = 'Your Company Name'
  462.    @ 16, CENTR(msg) SAY msg
  463.    msg = 'Your Street Address'
  464.    @ 17, CENTR(msg) SAY msg
  465.    msg = 'Your City, State, Zip'
  466.    @ 18, CENTR(msg) SAY msg
  467. return
  468.  
  469. *****************************************************
  470. procedure sub_ans_process( sub_choice, main_choice  )
  471. *****************************************************
  472. /*
  473.    if the left or right arrow was pressed, this procedure will increment
  474.    or decrement the main_choice and stuff the keyboard with the return
  475.    key so that the next pull down menu will go into effect.
  476. */
  477.  
  478.    do case
  479.       case sub_choice = -1
  480.          main_choice = main_choice - 1
  481.          if main_choice = 0
  482.             main_choice = len(menu_names) + 1
  483.          endif
  484.          keyboard chr(13)
  485.  
  486.       case sub_choice = -2
  487.          main_choice = main_choice + 1
  488.          if main_choice = len(menu_names) + 2
  489.             main_choice = 1
  490.          endif
  491.          keyboard chr(13)
  492.    end case
  493. return
  494.  
  495. **************
  496. FUNCTION centr
  497. **************
  498. PARAMETERS in_string, in_length
  499. IF TYPE('in_length') = 'U'
  500.   in_length = 80
  501. ENDI
  502. RETURN INT((in_length - LEN(in_string))/2)