'=========================================================================== ' Subject: GUI EASYMENU Date: 10-09-97 (12:11) ' Author: Rodney Steele Code: QB, QBasic, PDS ' Origin: rsteele@cs.mun.ca Packet: MENU.ABC '=========================================================================== 'Programmer: Rodney Steele 'E-Mail : rwsteele@geocities.com 'Web Page : http://www.geocities.com/siliconvalley/horizon/1099 'S-Mail : P.O.Box 1, Birchy Bay, NF., Canada, A0G 1E0 'Date : Oct. 9/97 'Version : 1.0 ' 'Hi, thanks for trying EasyMenu. After trying to find a good graphic menu 'system for screen 13 and not having any luck, I decided to write my own. 'This is it, 'EasyMenu'. This program was originally designed for screen 13, 'but with a few changes it now can be used in both 13 and 12. ' 'Please tell me what you think, or if you find a bug, or even if you have 'some ideas, email me. '---------------------------------------------------------------------------- ' Copyright 1997 by Rodney Steele ' ------------------------------- 'You are permitted to use this program provided that it is used in a 'non-commercial product and you must give credit eithor on screen or in a 'credit or documention file stating: ' ' "Menu, Font13, and Mouse Routines created by Rodney Steele". ' 'This Program is provides 'as-is' no waranties expressed or implied. 'Use at own risk. '---------------------------------------------------------------------------- 'NOTE 'Since not much error detection code is used, data on the far right and at 'the bottom of the screen will not be printed if it extends behond the screen 'limits. If you experience data loss, reduce the size of the data in the main 'or sub-menu options. '----- 'To Start your own menu: 'All you have to do is define three constants, type in your menu options, and 'call InitMouse to initilized the menu system, then call the function Menu. 'After choosing a option it will return a unique number for that option. 'More details below on what to change to create your own menu. '----- 'To calculate the unique number for an option, use this equation 'Unique number = (column-1) * nsmo + row '----- 'Run this program to try the demo!! '---------------------------------------------------------------------------- DECLARE FUNCTION Menu% () DECLARE FUNCTION InitMouse% () DECLARE SUB SetPointerMouse () DECLARE SUB SpeedMouse (x%, y%, d%) DECLARE SUB ClearMouse () DECLARE SUB CallMouse (ax%, bx%, cx%, dx%, es%) DECLARE SUB ShowMouse () DECLARE SUB PutMouse (x%, y%) DECLARE SUB HideMouse () DECLARE SUB DataMouse (lbpressed%, rbpressed%, x%, y%) DECLARE SUB MenuInit () DECLARE SUB Font13 (text$, x%, y%, col%) DECLARE SUB XYMouse (x1%, y1%, x2%, y2%) DEFINT A-Z CONST false = 0, true = NOT false '---------------------------------------------------------------------------- ' #1 '----- 'You must change the constant " nmmo ". Number of main menu options, to the 'number you are using. '----- 'You must change the constant " nsmo ". Number of submenu options, to the 'max number you are using in a submenu. Also note, you must include in the 'count the number of seperation lines "-". '----- 'You also have a choice bewteen modes 12 or 13, select as described below. '----- CONST nmmo = 7 'number of main menu options in Sm(0) CONST nsmo = 8 'largest number of sub-menu options from Sm(1) to Sm(nmmo) 'Sm(6) and Sm(1) below are the largest with 8 items. CONST mm = 1 'screen 12 = 2, screen 13 = 1 '---------------------------------------------------------------------------- IF nmmo > nsmo THEN largest = nmmo ELSE largest = nsmo DIM SHARED smd(0 TO nmmo, 0 TO largest) AS STRING DIM SHARED Sm(0 TO nmmo) AS STRING DIM SHARED da(0 TO nmmo, 1 TO 3), xloc(0 TO nmmo) DIM SHARED SubMenuPrinted, y, x, Mouse(0 TO 44) DIM SHARED ax, bx, cx, dx, es DIM SHARED lbpressed, rbpressed '---------------------------------------------------------------------------- ' #2 '----- 'Store your main menu options in identifier Sm(0). 'SM(1) to Sm(nmmo) are where the submenu options are stored. '----- 'The subtraction sign "-" is used to produce a seperation line, and must be 'seperated by commas in the submenu options, thats Sm(1) to Sm(nmmo). 'Note, no "-" signs in the main menu identifier Sm(0). '----- 'You must have a comma at the end of all data strings. That is from Sm(0) to 'Sm(nmmo) the last character inside the quotes MUST be a comma. '----- 'Do add spaces before and/or after commas to increase space between words. 'Each space is equal to one pixel. 'DON'T add spaces with the subtraction sign "-" 'Only use AlphNumeric characters, except for the subtraction sign and comma. '----- Sm(0) = "file,edit,view,search,run,debug,options," Sm(1) = "new,open,save,save as,-,print,-,exit," Sm(2) = "cut,copy,paste,clear,new subroutine,new function," Sm(3) = "sub,split,output screen," Sm(4) = "find,repeat last find,change," Sm(5) = "start,restart,continue," Sm(6) = "step,procedure step,-,trace on,-,toggle breakpoint,clear breakpoint,set next statement," Sm(7) = "display,help path,syntax checking" '---------------------------------------------------------------------------- 'These are the color constants, change if you wish. 'I have chosen colors below that will work in both modes. CONST mmfontcol = 15 'Main menu font color CONST mmBackCol = 4 'Main menu background color CONST mmfhcol = 0 'Main menu font in highlight area CONST mmHLCol = 10 'Main menu highlight color CONST smfontcol = 0 'Submenu font color CONST smBackCol = 7 'Submenu background color CONST HighLightCol = 10 'Highlight color CONST outlinecol = 0 'Outline and dividing line color '---------------------------------------------------------------------------- Mouse: 'Data for new mouse pointer. DATA &HF7FF,&HE3FF,&HC1FF,&H80FF,&HE3FF,&HE3FF,&HE3FF,&HE3FF DATA &HFFFF,&HFFFF,&HFFFF,&HFFFF,&HFFFF,&HFFFF,&HFFFF,&HFFFF DATA &H0 ,&H800 ,&H1C00,&H3E00,&H800 ,&H800 ,&H800 ,&H800 DATA &H0 ,&H0 ,&H0 ,&H0 ,&H0 ,&H0 ,&H0 ,&H0 '---------------------------------------------------------------------------- IF mm = 1 THEN SCREEN 13 ELSE SCREEN 12 'User's program starts here lbpressed = false rbpressed = false finished = false IF InitMouse THEN SetPointerMouse 'Use a different mouse pointer IF mm = 1 THEN 'Limit mouse to this area XYMouse 0, 0, 647, 199 ELSE XYMouse 0, 0, 640, 479 END IF SpeedMouse 50, 50, 64 'Set regular and double speed PutMouse 100, 50 'Place mouse at this point PAINT (100, 100), 3 'Color screen MenuInit 'Setup EasyMenu 'Draw some boxes FOR t = 1 TO 50 LINE (INT(RND * 319) + 1, INT(RND * 192) + 8)-(INT(RND * 319) + 1, INT(RND * 192) + 8), 4, B NEXT ShowMouse 'Turn on mouse DO 'Main program loop ClearMouse 'Clear mouse buffer DataMouse lbpressed, rbpressed, x, y 'Get mouse data IF y <= 6 * mm THEN 'Detect when mouse is on menu op = Menu 'Call EasyMenu function LOCATE 13, 1: PRINT STRING$(20, " ") LOCATE 13, 1 SELECT CASE op CASE 0 PRINT "No choice selected." CASE 1 PRINT "New" CASE 2 PRINT "Open" CASE 3 PRINT "Save" CASE 6 PRINT "Exit" 'Quit program finished = true CASE 4, 5, 7 TO 50 PRINT "Not defined!!" END SELECT LOCATE 15, 1: PRINT "You choice was menu option #"; op LOCATE 17, 1: PRINT "This is mode "; IF mm = 1 THEN PRINT "13"; ELSE PRINT "12"; END IF PRINT " to try mode" IF mm = 1 THEN PRINT "12"; ELSE PRINT "13"; END IF PRINT " change the constant mm" LOCATE 20, 1: PRINT "Choose exit to quit." END IF LOOP UNTIL finished HideMouse ELSE PRINT "Mouse not found!!!" END IF END SUB CallMouse (ax, bx, cx, dx, es) 'Get data by calling ML program. DEF SEG = VARSEG(Mouse(0)) CALL Absolute(ax, bx, cx, dx, es, VARPTR(Mouse(0))) DEF SEG END SUB SUB ClearMouse 'Clear mouse buffer. DO DataMouse lbpressed, rbpressed, x, y LOOP WHILE rbpressed OR lbpressed END SUB SUB DataMouse (lbpressed, rbpressed, x, y) 'Return current x, y position of mouse and if a button is pressed. ax = 3 CallMouse ax, bx, cx, dx, es IF mm = 2 THEN div = 1 ELSE div = 2 x = cx \ div y = dx lbpressed = (bx AND 1) <> 0 rbpressed = (bx AND 2) <> 0 END SUB SUB Font13 (text$, x, y, col) fp$ = "" FOR t = 1 TO LEN(text$) letter$ = UCASE$(MID$(text$, t, 1)) IF letter$ = "A" THEN fp$ = fp$ + "u4r2d2nl2d2br2" ELSEIF letter$ = "B" THEN fp$ = fp$ + "u4r2d2nl2d2nl2br2" ELSEIF letter$ = "C" THEN fp$ = fp$ + "nr2u4r2bd4br2" ELSEIF letter$ = "D" THEN fp$ = fp$ + "u4r1f1d2g1l1br4" ELSEIF letter$ = "E" THEN fp$ = fp$ + "nr2u2nr1u2r2bd4br2" ELSEIF letter$ = "F" THEN fp$ = fp$ + "u2nr1u2r2bd4br2" ELSEIF letter$ = "G" THEN fp$ = fp$ + "nr2u4r2bd2d2br2" ELSEIF letter$ = "H" THEN fp$ = fp$ + "u4bd2r2nu2d2br2" ELSEIF letter$ = "I" THEN fp$ = fp$ + "r2l1u4nl1r1bd4br2" ELSEIF letter$ = "J" THEN fp$ = fp$ + "nu1r2u4nl1r1bd4 br2" ELSEIF letter$ = "K" THEN fp$ = fp$ + "nu4bu2ne2f2br2" ELSEIF letter$ = "L" THEN fp$ = fp$ + "nu4r2br2" ELSEIF letter$ = "M" THEN fp$ = fp$ + "u4f2e2d4br2" ELSEIF letter$ = "N" THEN fp$ = fp$ + "u4f4u4bd4br2" ELSEIF letter$ = "O" THEN fp$ = fp$ + "br1h1u2e1f1d2g1br3" ELSEIF letter$ = "P" THEN fp$ = fp$ + "u4r2d2nl2bd2br2" ELSEIF letter$ = "Q" THEN fp$ = fp$ + "br1h1u2e1r1f1d2g1l1bu1br1f1r1br2" ELSEIF letter$ = "R" THEN fp$ = fp$ + "u4r2d2l2f2br2" ELSEIF letter$ = "S" THEN fp$ = fp$ + "r2u2l2u2r2bd4br2" ELSEIF letter$ = "T" THEN fp$ = fp$ + "br1u4nl1r1bd4br2" ELSEIF letter$ = "U" THEN fp$ = fp$ + "nu4r2nu4br2" ELSEIF letter$ = "V" THEN fp$ = fp$ + "bu4d3f1e1u3bd4br2" ELSEIF letter$ = "W" THEN fp$ = fp$ + "nu4e2f2u4bd4br2" ELSEIF letter$ = "X" THEN fp$ = fp$ + "ne4br4nh4br2" ELSEIF letter$ = "Y" THEN fp$ = fp$ + "br1u2l1u2br2d2l1bd2br3" ELSEIF letter$ = "Z" THEN fp$ = fp$ + "nr2u1e2u1l2bd4br4" ELSEIF letter$ = "0" THEN fp$ = fp$ + "u4r2d4nl2br2" ELSEIF letter$ = "1" THEN fp$ = fp$ + "br1u4g1br1bd3br2" ELSEIF letter$ = "2" THEN fp$ = fp$ + "nr2u1e2u1l2bd4br4" ELSEIF letter$ = "3" THEN fp$ = fp$ + "r2u2nl2u2nl2bd4br2" ELSEIF letter$ = "4" THEN fp$ = fp$ + "bu2nu2r2nu2d2br2" ELSEIF letter$ = "5" THEN fp$ = fp$ + "r2u2l2u2r2bd4br2" ELSEIF letter$ = "6" THEN fp$ = fp$ + "bu2r2d2l2u4r2bd4br2" ELSEIF letter$ = "7" THEN fp$ = fp$ + "bu3u1r2d4br2" ELSEIF letter$ = "8" THEN fp$ = fp$ + "nr2u4r2d2nl2d2br2" ELSEIF letter$ = "9" THEN fp$ = fp$ + "br2u4l2d2r2bd2br2" ELSE fp$ = fp$ + "br1" END IF NEXT 'Change size of font for screen mode. IF mm = 2 THEN size$ = "s8 c" ELSE size$ = "s4 c" location$ = size$ + STR$(col) + " bm" + STR$(x) + "," + STR$(y) + " x" DRAW location$ + VARPTR$(fp$) 'Print data. END SUB SUB HideMouse ax = 2 CallMouse ax, bx, cx, dx, es END SUB FUNCTION InitMouse 'Write ML routine to memory. d$ = "5589E5568B760E8B048B760C8B1C8B760A8B0C8B76088B148B76068E04CD338B760E89048B760C891C8B760A890C8B760889148B76068C045E5DCB" DEF SEG = VARSEG(Mouse(0)) FOR t = 0 TO 87 POKE VARPTR(Mouse(0)) + t, VAL("&H" + MID$(d$, t * 2 + 1, 2)) NEXT 'Check for mouse. ax = 0 CallMouse ax, bx, cx, dx, es InitMouse = ax END FUNCTION FUNCTION Menu 'This function returns a unique number for an option that is chosen and well 'displaying and erasing the sub-menus. DIM smenu(1) rightside = 319 * mm 'Edges of sub-menu leftside = 0 ' BottomSide = 199 ' mc = 0 SubMenuPrinted = false pc = 0 '---------------------------------------------------------------------------- 'Main Menu routine DO GOSUB GetMouseInfo IF y <= 6 * mm THEN 'If mouse on main menu area... pc = mc FOR t = 1 TO nmmo 'Locate option picked. IF x < xloc(t) THEN EXIT FOR NEXT mc = t IF mc = nmmo + 1 THEN 'Erase if not on a main menu option. GOSUB EraseOldMenu ' thats the far right area. ELSE IF mc <> pc THEN 'If different choice then print menu. IF SubMenuPrinted THEN 'Erase if leaving one menu option for GOSUB EraseOldMenu ' another. END IF GOSUB PrintNewMenu 'and print new sub-menu. ELSE IF NOT SubMenuPrinted THEN GOSUB PrintNewMenu END IF END IF ELSEIF y > 6 * mm AND SubMenuPrinted THEN 'On sub-menu area. pc = mc mmchoice = 0 'Set choice to zero. GOSUB MoveHighLight 'Highlight current option. IF mmchoice <> 0 THEN EXIT DO 'If choice selected exit loop. ELSEIF y > 6 * mm AND NOT SubMenuPrinted THEN 'Leaving sub-menu below main. EXIT DO END IF LOOP IF SubMenuPrinted THEN GOSUB EraseOldMenu IF pc <> 0 THEN pc = pc - 1 Menu = mmchoice + pc * nsmo 'Calculate the unique number. ELSE 'No option picked leaving function. Menu = 0 'Set Menu to no option. END IF EXIT FUNCTION '---------------------------------------------------------------------------- MoveHighLight: pjump = 10 * mm preWordIndex = 1 DO 'Find new highlight option. HideMouse WordIndex = 0: yy = y jump = 3 * mm: choice = 0 IF yy > 9 * mm THEN DO WordIndex = WordIndex + 1 IF yy > jump + (6 * mm) THEN IF smd(mc, WordIndex) = "-" THEN jump = jump + 8 * mm WordIndex = WordIndex + 1 choice = choice + 1 ELSE jump = jump + 7 * mm choice = choice + 1 END IF ELSE WordIndex = WordIndex - 1 EXIT DO END IF LOOP UNTIL WordIndex = da(mc, 1) 'Only redraw if a different option is choosen. IF preWordIndex <> WordIndex THEN 'Erase old highligh and reprint option. LINE (emm1 + 3, pjump)-(emm3 - 3, pjump + (6 * mm)), smBackCol, BF Font13 smd(mc, preWordIndex), emm1 + 5, pjump + 5 * mm, smfontcol 'Print new highlight and option. LINE (emm1 + 3, jump)-(emm3 - 3, jump + 6 * mm), HighLightCol, BF Font13 smd(mc, WordIndex), emm1 + 5, jump + 5 * mm, smfontcol preWordIndex = WordIndex pjump = jump END IF END IF ShowMouse GOSUB GetMouseInfo 'User picks a choice. IF lbpressed THEN mmchoice = choice 'If leaving sub-menu boundaries then erase. IF x < leftside OR x > rightside OR y > BottomSide THEN GOSUB EraseOldMenu LOOP WHILE SubMenuPrinted AND y > 6 * mm AND NOT lbpressed RETURN '---------------------------------------------------------------------------- EraseOldMenu: IF SubMenuPrinted THEN HideMouse 'Erase sub-menu by replacing what was under it. PUT (emm1, 7 * mm), smenu, PSET 'Redraw main menu option highlight and word. LINE (emm1, 6 * mm)-(emm2 - 1, 0), mmBackCol, BF Font13 smd(0, emm0), emm1 + 2, 5 * mm, mmfontcol SubMenuPrinted = false rightside = 319 * mm leftside = 0 BottomSide = 199 ShowMouse END IF RETURN '---------------------------------------------------------------------------- PrintNewMenu: HideMouse 'Calculate data used in drawing sub-menu. emm0 = mc emm1 = xloc(mc - 1) emm2 = xloc(mc) emm3 = emm1 + da(mc, 2) + 9 emm4 = (12 + (da(mc, 1) - da(mc, 3)) * 7 + da(mc, 3)) * mm 'Define sides of sub-menu boundaries. rightside = emm3 leftside = emm1 BottomSide = emm4 SubMenuPrinted = true 'Highlight main menu option and print option. LINE (emm1, 6 * mm)-(emm2 - 1 * mm, 0), mmHLCol, BF Font13 smd(0, mc), emm1 + 2, 5 * mm, mmfhcol 'Save area where menu will be printed, and draw sub-menu background, outline, 'and highlight. REDIM smenu((emm3 - emm1 + 1) * (emm4 - (7 * mm) + 1) / 2 + 2) GET (emm1, 7 * mm)-(emm3, emm4), smenu LINE (emm1, 7 * mm)-(emm3, emm4), smBackCol, BF LINE (emm1 + 2, 9 * mm)-(emm3 - 2, emm4 - 2 * mm), outlinecol, B LINE (emm1 + 3, 10 * mm)-(emm3 - 3, 16 * mm), HighLightCol, BF 'Draw seperating lines and print options. jump = 9 * mm FOR t = 1 TO da(mc, 1) IF smd(mc, t) = "-" THEN jump = jump + 1 * mm LINE (emm1 + 3, jump)-(emm3 - 2, jump), outlinecol ELSE jump = jump + 6 * mm Font13 smd(mc, t), emm1 + 5, jump, smfontcol jump = jump + 1 * mm END IF NEXT ShowMouse RETURN '---------------------------------------------------------------------------- GetMouseInfo: 'Clear mouse buffer. ClearMouse 'Get current location storing in px and py DataMouse lbpressed, rbpressed, x, y px = x py = y 'Wait until mouse has moved or a button is selected. DO DataMouse lbpressed, rbpressed, x, y LOOP UNTIL px <> x OR py <> y OR lbpressed OR rbpressed RETURN END FUNCTION SUB MenuInit 'Find number of items for each main menu item and also the length of the 'longest item. FOR i = 0 TO nmmo INums = 0 counter = 0: count = 0: pcount = 1 HiCounter = 0 FOR t = 1 TO LEN(Sm(i)) letter$ = UCASE$(MID$(Sm(i), t, 1)) IF letter$ = "," THEN INums = INums + 1 smd(i, INums) = MID$(Sm(i), pcount, count) pcount = pcount + count + 1 count = 0 IF counter > HiCounter THEN HiCounter = counter counter = 0 ELSE IF INSTR("MNWXQ", letter$) <> 0 THEN length = 6 * mm ELSEIF INSTR("ABCDEFGHIJKLOPRSTUVYZ", letter$) <> 0 THEN length = 4 * mm ELSEIF letter$ = "-" THEN da(i, 3) = da(i, 3) + 1 length = 0 ELSEIF letter$ = " " THEN length = 1 ELSEIF INSTR("0123456789", letter$) <> 0 THEN length = 3 * mm END IF count = count + 1 counter = counter + length END IF NEXT da(i, 1) = INums da(i, 2) = HiCounter NEXT '----- 'Compute location for x; used to detect which option is choosen. xloc(0) = 0 total = 0 count = 0 FOR t = 1 TO LEN(Sm(0)) letter$ = UCASE$(MID$(Sm(0), t, 1)) IF INSTR("MNWXQ", letter$) <> 0 THEN total = total + 6 * mm ELSEIF INSTR("ABCDEFGHIJKLOPRSTUVYZ", letter$) <> 0 THEN total = total + 4 * mm ELSEIF letter$ = " " THEN total = total + 1 * mm ELSEIF INSTR("0123456789", letter$) <> 0 THEN total = total + 3 * mm ELSEIF letter$ = "," THEN total = total + 3 count = count + 1 xloc(count) = total END IF NEXT '----- 'Draw main menu and display options. LINE (0, 0)-(320 * mm, 6 * mm), mmBackCol, BF FOR t = 1 TO nmmo Font13 smd(0, t), xloc(t - 1) + 2, 5 * mm, mmfontcol NEXT END SUB SUB PutMouse (x, y) ax = 4 cx = x dx = y CallMouse ax, bx, cx, dx, es END SUB SUB SetPointerMouse 'Create a new smaller pointer for the mouse. DIM ms(1 TO 32) AS INTEGER RESTORE Mouse FOR t = 1 TO 32 READ ms(t) NEXT ax = 9 IF mm = 1 THEN bx = 8 ELSE bx = 5 'Move column of cursor hot spot. cx = 0 dx = VARPTR(ms(1)) es = VARSEG(ms(1)) CallMouse ax, bx, cx, dx, es END SUB SUB ShowMouse ax = 1 CallMouse ax, bx, cx, dx, es END SUB SUB SpeedMouse (x, y, d) 'Define mickey/pixel ratio. 'How many mickeys per 8 pixel. ax = 15 cx = x 'Default 8. dx = y 'Default 16. CallMouse ax, bx, cx, dx, es 'Define double-speed threshold. 'If speed exceeds threshold, the cursor's motion is doubled. ax = 19 dx = d '0 = default for 64/second CallMouse ax, bx, cx, dx, es END SUB SUB XYMouse (x1, y1, x2, y2) 'Set boundaries. ax = 7 cx = x1 dx = x2 CallMouse ax, bx, cx, dx, es ax = 8 cx = y1 dx = y2 CallMouse ax, bx, cx, dx, es END SUB