'=========================================================================== ' Subject: CUSTOMIZABLE MENUING SYSTEM Date: 08-21-98 (17:07) ' Author: Anders Olofsson Code: QB, QBasic, PDS ' Origin: anders.olofsson@mail.bip.net Packet: MENU.ABC '=========================================================================== ' Menuing system, by Anders Olofsson 1998. ' ' Here is a simple & easy to use menuing system with hotkeys and shadows. ' ' See the "InitMenus" sub for more information about ' making menus and menuitems. ' ' e-mail: anders.olofsson@mail.bip.net ' DEFINT A-Z '$DYNAMIC DECLARE FUNCTION AltKey$ (KB$) DECLARE SUB DisableMenuItem (Menu%, Item%) DECLARE SUB EnableMenuItem (Menu%, Item%) DECLARE SUB MakeMenu (MenuNum%, Col%, MenuName$) DECLARE SUB AddMenuItem (MenuNum%, Item$) DECLARE SUB SetMenuItemColor (Menu%, Item%, ForeColor%, BackColor%) DECLARE SUB InitMenus () DECLARE SUB DrawMenuBar (HotKeys%, SelectedItem%) DECLARE FUNCTION MenuItemSelected% (K$) TYPE MenuType MenuName AS STRING * 15 MenuLen AS INTEGER NumItems AS INTEGER CurrentItem AS INTEGER Col AS INTEGER ForeColor AS INTEGER BackColor AS INTEGER HighlightColor AS INTEGER DisabledColor AS INTEGER END TYPE TYPE MenuItemType Item AS STRING * 40 Disabled AS INTEGER ForeColor AS INTEGER BackColor AS INTEGER END TYPE TYPE FileFindBuf DOS AS STRING * 21: Attributes AS STRING * 1 AccessTime AS STRING * 2: AccessDate AS STRING * 2 FileSize AS LONG: Filename AS STRING * 13 END TYPE TYPE RegTypeX ax AS INTEGER: bx AS INTEGER: cx AS INTEGER dx AS INTEGER: bp AS INTEGER: si AS INTEGER di AS INTEGER: flags AS INTEGER: ds AS INTEGER es AS INTEGER END TYPE '--- Menu system DIM SHARED Menus(1 TO 15) AS MenuType 'Max 15 menus. DIM SHARED MenuItems(1 TO 15, 1 TO 30) AS MenuItemType 'Max 30 menuitems in 'each menu. InitMenus 'Read data into the variables above. CLS : WIDTH 80, 25 Rows = 25 Restart: DEF SEG = &HB800 FOR I = 0 TO 7999 STEP 6 POKE I, 65 POKE I + 1, 16 + 9 POKE I + 2, 66 POKE I + 3, 16 POKE I + 4, 67 POKE I + 5, 16 NEXT DrawMenuBar 0, 0 COLOR 10, 5 LOCATE Rows \ 2 - 1, 20: PRINT " You selected: " DO 'Call the menuing system and get menuchoice & key presses MenuChoice = MenuItemSelected(Keys$) IF LEN(Keys$) THEN COLOR 14, 1 LOCATE Rows \ 2, 21 PRINT " Keypress: "; Keys$; SPACE$(30 - LEN(Keys$)) END IF SELECT CASE MenuChoice ' Format is easy! - Menu number * 100 + Menu item ' (If you select item 10 from menu 5 that's 510!) CASE 301 TO 303 ' Menu 3 choice 1 EnableMenuItem 3, 1: EnableMenuItem 3, 2: EnableMenuItem 3, 3 DisableMenuItem 3, MenuChoice - 300 IF MenuChoice - 300 = 1 THEN Rows = 25 ELSEIF MenuChoice - 300 = 2 THEN Rows = 43 ELSEIF MenuChoice - 300 = 3 THEN Rows = 50 END IF WIDTH 80, Rows: GOTO Restart CASE IS > 0 ' Other choice COLOR 14, 1 LOCATE Rows \ 2, 41 - LEN(MenuItems(MenuChoice \ 100, MenuChoice MOD 100).Item) \ 2 PRINT " "; FOR I = 1 TO LEN(MenuItems(MenuChoice \ 100, MenuChoice MOD 100).Item) IF MID$(MenuItems(MenuChoice \ 100, MenuChoice MOD 100).Item, I, 1) <> "^" THEN PRINT MID$(MenuItems(MenuChoice \ 100, MenuChoice MOD 100).Item, I, 1); NEXT END SELECT LOOP UNTIL MenuChoice = 109 REM $STATIC SUB AddMenuItem (MenuNum, MenuItem$) Menus(MenuNum).NumItems = Menus(MenuNum).NumItems + 1 MenuItems(MenuNum, Menus(MenuNum).NumItems).Item = MenuItem$ MenuItems(MenuNum, Menus(MenuNum).NumItems).Disabled = 0 MenuItems(MenuNum, Menus(MenuNum).NumItems).ForeColor = 0 MenuItems(MenuNum, Menus(MenuNum).NumItems).BackColor = 7 END SUB FUNCTION AltKey$ (KB$) 'This function returns the key that was pressed together with alt. IF LEN(KB$) <> 2 THEN EXIT FUNCTION AltTable$ = SPACE$(15) + "QWERTYUIOP ASDFGHJKL ZXCVBNM" + SPACE$(69) + "1234567890" AltKey$ = MID$(AltTable$, ASC(RIGHT$(UCASE$(KB$), 1)), 1) END FUNCTION SUB DisableMenuItem (Menu, Item) MenuItems(Menu, Item).Disabled = -1 END SUB SUB DrawMenuBar (HotKeys, SelectedItem) IF SelectedItem = 0 THEN FOR X = 1 TO UBOUND(Menus) IF Menus(X).MenuLen = 0 AND X > 1 THEN MaxMenus = X - 1: EXIT FOR NEXT COLOR 0, 7: LOCATE 1, 1: PRINT SPACE$(80) FOR X = 1 TO MaxMenus IF Menus(X).MenuLen THEN IF HotKeys = 0 THEN LOCATE 1, Menus(X).Col: COLOR Menus(X).ForeColor, Menus(X).BackColor FOR Z = 1 TO Menus(X).MenuLen IF MID$(Menus(X).MenuName, Z, 1) <> "^" THEN PRINT MID$(Menus(X).MenuName, Z, 1); NEXT ELSE LOCATE 1, Menus(X).Col: COLOR Menus(X).ForeColor, Menus(X).BackColor FOR Z = 1 TO Menus(X).MenuLen IF MID$(Menus(X).MenuName, Z, 1) = "^" THEN COLOR Menus(X).HighlightColor, Menus(X).BackColor ELSE PRINT MID$(Menus(X).MenuName, Z, 1); COLOR Menus(X).ForeColor, Menus(X).BackColor END IF NEXT END IF END IF NEXT ELSE COLOR Menus(SelectedItem).BackColor, Menus(SelectedItem).ForeColor IF HotKeys = 0 THEN LOCATE 1, Menus(SelectedItem).Col FOR Z = 1 TO Menus(SelectedItem).MenuLen IF MID$(Menus(SelectedItem).MenuName, Z, 1) <> "^" THEN PRINT MID$(Menus(SelectedItem).MenuName, Z, 1); NEXT ELSE LOCATE 1, Menus(SelectedItem).Col FOR Z = 1 TO Menus(SelectedItem).MenuLen IF MID$(Menus(SelectedItem).MenuName, Z, 1) = "^" THEN COLOR Menus(SelectedItem).HighlightColor, Menus(SelectedItem).ForeColor ELSE PRINT MID$(Menus(SelectedItem).MenuName, Z, 1); COLOR Menus(SelectedItem).BackColor, Menus(SelectedItem).ForeColor END IF NEXT END IF END IF END SUB SUB EnableMenuItem (Menu, Item) MenuItems(Menu, Item).Disabled = 0 END SUB SUB InitMenus '-------------------- 'Menu number '  MakeMenu 1, 3, " ^File " '-------------------- ' Menu start column '  MakeMenu 2, 9, " ^Edit " '-------------------- 'Name (^ highlights the "O") '  MakeMenu 3, 15, " ^Options " MakeMenu 4, 24, " ^Help " MakeMenu 5, 30, " ^Info " MakeMenu 6, 36, " ^Colors " '-------- Add the menuitems AddMenuItem 1, "^New document" AddMenuItem 1, "^Open document..." AddMenuItem 1, "^Save" AddMenuItem 1, "Save ^as..." AddMenuItem 1, "~" '~ = Dividing line AddMenuItem 1, "^Print..." AddMenuItem 1, "Disabled item!" DisableMenuItem 1, 7 AddMenuItem 1, "~" AddMenuItem 1, "E^xit" SetMenuItemColor 1, 9, 4, 7 'Set exit menu-item color AddMenuItem 2, "^Undo" AddMenuItem 2, "Cu^t" AddMenuItem 2, "^Copy" AddMenuItem 2, "^Paste" DisableMenuItem 2, 2: DisableMenuItem 2, 3 AddMenuItem 2, "~" AddMenuItem 2, "^Find..." AddMenuItem 2, "^Repeat last find..." AddMenuItem 2, "Find ^next..." AddMenuItem 2, "^Replace..." AddMenuItem 3, "^Set screen resolution to 25 Rows" AddMenuItem 3, "S^et screen resolution to 43 Rows" AddMenuItem 3, "Se^t screen resolution to 50 Rows" DisableMenuItem 3, 1 'Disable 25 Rows resolution choice - since it is used 'as default in the startup... AddMenuItem 4, "^Help..." AddMenuItem 4, "^Ab^ou^t.^.." AddMenuItem 5, "Hot keys are optional" AddMenuItem 5, "Use them ^on^ly if you w^an^t!" SetMenuItemColor 5, 2, 10, 7 AddMenuItem 6, "^Colors!" AddMenuItem 6, "C ^o l o r s!" AddMenuItem 6, "Co^lors!" AddMenuItem 6, "~" AddMenuItem 6, "C o l ^o r s!" AddMenuItem 6, "Colo^rs!" AddMenuItem 6, "C o l o r ^s!" AddMenuItem 6, "~" AddMenuItem 6, "^Colors!" AddMenuItem 6, "C o ^l o r s!" AddMenuItem 6, "Color^s!" AddMenuItem 6, "~" AddMenuItem 6, "C o l o r ^s!" AddMenuItem 6, "Co^lors!" AddMenuItem 6, "^C o l o r s!" Menus(6).BackColor = 3: Menus(6).ForeColor = 4 FOR I = 1 TO 3 SetMenuItemColor 6, I, 10, 0 SetMenuItemColor 6, I + 4, 3, 11 SetMenuItemColor 6, I + 8, 9, 2 SetMenuItemColor 6, I + 12, 2, 5 NEXT END SUB SUB MakeMenu (MenuNum, Col, MenuName$) Menus(MenuNum).Col = Col Menus(MenuNum).ForeColor = 0: Menus(MenuNum).BackColor = 7 Menus(MenuNum).HighlightColor = 15: Menus(MenuNum).MenuName = MenuName$ Menus(MenuNum).CurrentItem = 1: Menus(MenuNum).MenuLen = LEN(MenuName$) Menus(MenuNum).DisabledColor = 8 END SUB FUNCTION MenuItemSelected (Keyboard$) DEF SEG = &H40: AltPressed = (PEEK(&H17) AND 8) <> 0: Keyboard$ = INKEY$ IF AltPressed = 0 THEN EXIT FUNCTION LOCATE , , 0: DrawMenuBar 1, 0: CurrentMenu = 1: CurrentItem = 1 'Find out number of menus... FOR X = 1 TO UBOUND(Menus) IF Menus(X).MenuLen = 0 AND X > 1 THEN MaxMenus = X - 1: EXIT FOR NEXT DIM HotKeys$(1 TO MaxMenus, 0 TO UBOUND(MenuItems, 2)) FOR X = 1 TO MaxMenus IF INSTR(Menus(X).MenuName, "^") THEN HotKeys$(X, 0) = UCASE$(MID$(Menus(X).MenuName, INSTR(Menus(X).MenuName, "^") + 1, 1)) FOR Y = 1 TO Menus(X).NumItems IF INSTR(MenuItems(X, Y).Item, "^") THEN HotKeys$(X, Y) = UCASE$(MID$(MenuItems(X, Y).Item, INSTR(MenuItems(X, Y).Item, "^") + 1, 1)) NEXT NEXT DO DEF SEG = &H40: AltPressed = (PEEK(&H17) AND 8) <> 0 IF AltPressed = 0 THEN EXIT DO K$ = INKEY$: Keyboard$ = K$: K$ = UCASE$(K$) IF LEN(K$) = 2 THEN KCode$ = AltKey$(K$) FOR X = 1 TO MaxMenus IF LEN(HotKeys$(X, 0)) AND HotKeys$(X, 0) = KCode$ THEN CurrentMenu = X GOTO GetMenuDone END IF NEXT END IF IF LEN(K$) THEN EXIT FUNCTION LOOP GetMenuChoice: DrawMenuBar 1, 0 DrawMenuBar 1, CurrentMenu DO K$ = UCASE$(INKEY$) IF K$ = CHR$(0) + CHR$(80) OR K$ = CHR$(0) + CHR$(72) OR K$ = CHR$(13) THEN EXIT DO IF K$ = CHR$(0) + CHR$(75) THEN CurrentMenu = CurrentMenu - 1: IF CurrentMenu < LBOUND(Menus) THEN CurrentMenu = MaxMenus DrawMenuBar 1, 0: DrawMenuBar 1, CurrentMenu: K$ = "" ELSEIF K$ = CHR$(0) + CHR$(77) THEN CurrentMenu = (CurrentMenu MOD MaxMenus) + 1 DrawMenuBar 1, 0: DrawMenuBar 1, CurrentMenu: K$ = "" END IF IF LEN(K$) THEN FOR X = 1 TO MaxMenus IF K$ = HotKeys$(X, 0) THEN CurrentMenu = X: EXIT DO NEXT END IF DEF SEG = &H40: AltPressed = (PEEK(&H17) AND 8) <> 0 IF AltPressed THEN AltWasPressed = -1 IF AltPressed = 0 AND AltWasPressed = 1 THEN DrawMenuBar 0, 0 EXIT FUNCTION END IF IF AltWasPressed = -1 THEN AltWasPressed = 1 LOOP GetMenuDone: DrawMenuBar 0, 0 SCREEN 0, , 2, 0: PCOPY 0, 1: PCOPY 0, 2 GOSUB DrawCurrentMenu DO: DEF SEG = &H40: AltPressed = (PEEK(&H17) AND 8) <> 0: LOOP UNTIL AltPressed = 0 DO DEF SEG = &H40: AltPressed = (PEEK(&H17) AND 8) <> 0 IF AltPressed THEN DO: DEF SEG = &H40: AltPressed = (PEEK(&H17) AND 8) <> 0: LOOP UNTIL AltPressed = 0 PCOPY 1, 0: SCREEN 0, , 0, 0 GOTO GetMenuChoice END IF Key$ = UCASE$(INKEY$) SELECT CASE Key$ CASE CHR$(0) + CHR$(77) 'Right CurrentMenu = (CurrentMenu MOD MaxMenus) + 1 GOSUB DrawCurrentMenu CASE CHR$(0) + CHR$(75) 'Left CurrentMenu = CurrentMenu - 1: IF CurrentMenu < LBOUND(Menus) THEN CurrentMenu = MaxMenus GOSUB DrawCurrentMenu CASE CHR$(0) + CHR$(72) 'Up DO Menus(CurrentMenu).CurrentItem = Menus(CurrentMenu).CurrentItem - 1 IF Menus(CurrentMenu).CurrentItem < 1 THEN Menus(CurrentMenu).CurrentItem = Menus(CurrentMenu).NumItems LOOP UNTIL LEFT$(MenuItems(CurrentMenu, Menus(CurrentMenu).CurrentItem).Item, 1) <> "~" GOSUB DrawCurrentMenu CASE CHR$(0) + CHR$(80) 'Down DO Menus(CurrentMenu).CurrentItem = (Menus(CurrentMenu).CurrentItem MOD Menus(CurrentMenu).NumItems) + 1 LOOP UNTIL LEFT$(MenuItems(CurrentMenu, Menus(CurrentMenu).CurrentItem).Item, 1) <> "~" GOSUB DrawCurrentMenu CASE CHR$(13) IF MenuItems(CurrentMenu, Menus(CurrentMenu).CurrentItem).Disabled = 0 THEN SelectedItem = CurrentMenu * 100 + Menus(CurrentMenu).CurrentItem EXIT DO ELSE SOUND 200, .1 END IF CASE CHR$(27) EXIT DO CASE IS <> "" FOR I = 1 TO Menus(CurrentMenu).NumItems IF Key$ = HotKeys$(CurrentMenu, I) THEN SelectedItem = CurrentMenu * 100 + I EXIT DO END IF NEXT END SELECT LOOP SCREEN 0, , 0, 0: PCOPY 1, 0: PCOPY 0, 2 MenuItemSelected = SelectedItem EXIT FUNCTION DrawCurrentMenu: PCOPY 1, 2 DrawMenuBar 0, CurrentMenu MaxLen = 0 FOR I = 1 TO Menus(CurrentMenu).NumItems IF INSTR(MenuItems(CurrentMenu, I).Item, "^") THEN CurrentLen = LEN(RTRIM$(MenuItems(CurrentMenu, I).Item)) + 3 FOR L = 1 TO LEN(RTRIM$(MenuItems(CurrentMenu, I).Item)) IF MID$(MenuItems(CurrentMenu, I).Item, L, 1) = "^" THEN CurrentLen = CurrentLen - 1 NEXT ELSE CurrentLen = LEN(RTRIM$(MenuItems(CurrentMenu, I).Item)) + 2 END IF IF CurrentLen > MaxLen THEN MaxLen = CurrentLen NEXT COLOR Menus(CurrentMenu).ForeColor, Menus(CurrentMenu).BackColor LOCATE 2, Menus(CurrentMenu).Col - 1: PRINT CHR$(218) + STRING$(MaxLen, 196) + CHR$(191); LOCATE Menus(CurrentMenu).NumItems + 3, Menus(CurrentMenu).Col - 1: PRINT CHR$(192) + STRING$(MaxLen, 196) + CHR$(217); CH$ = CHR$(SCREEN(CSRLIN, POS(0))) + CHR$(SCREEN(CSRLIN, POS(0) + 1)) COLOR 8, 0: PRINT CH$; LOCATE Menus(CurrentMenu).NumItems + 4, Menus(CurrentMenu).Col FOR R = 1 TO MaxLen + 3 CH$ = CHR$(SCREEN(CSRLIN, POS(0))) COLOR 8, 0: PRINT CH$; NEXT FOR R = 3 TO Menus(CurrentMenu).NumItems + 2 LOCATE R, Menus(CurrentMenu).Col - 1 IF LEFT$(MenuItems(CurrentMenu, R - 2).Item, 1) <> "~" THEN COLOR Menus(CurrentMenu).ForeColor, Menus(CurrentMenu).BackColor PRINT CHR$(179); MenuTextFore = MenuItems(CurrentMenu, R - 2).ForeColor MenuTextBack = MenuItems(CurrentMenu, R - 2).BackColor IF MenuItems(CurrentMenu, R - 2).Disabled THEN MenuTextFore = Menus(CurrentMenu).DisabledColor IF R - 2 = Menus(CurrentMenu).CurrentItem THEN SWAP MenuTextFore, MenuTextBack COLOR MenuTextFore, MenuTextBack CurrentMenuText$ = " " + MenuItems(CurrentMenu, R - 2).Item: CurrentLen = MaxLen FOR L = 1 TO MaxLen IF MID$(CurrentMenuText$, L, 1) = "^" THEN CurrentLen = CurrentLen + 1 NEXT FOR L = 1 TO CurrentLen IF MID$(CurrentMenuText$, L, 1) <> "^" THEN PRINT MID$(CurrentMenuText$, L, 1); COLOR MenuTextFore, MenuTextBack ELSE IF MenuItems(CurrentMenu, R - 2).Disabled = 0 THEN COLOR Menus(CurrentMenu).HighlightColor, MenuTextBack END IF NEXT COLOR Menus(CurrentMenu).ForeColor, Menus(CurrentMenu).BackColor PRINT CHR$(179); CH$ = CHR$(SCREEN(CSRLIN, POS(0))) + CHR$(SCREEN(CSRLIN, POS(0) + 1)) COLOR 8, 0: PRINT CH$; ELSE COLOR Menus(CurrentMenu).ForeColor, Menus(CurrentMenu).BackColor PRINT CHR$(195) + STRING$(MaxLen, 196) + CHR$(180); CH$ = CHR$(SCREEN(CSRLIN, POS(0))) + CHR$(SCREEN(CSRLIN, POS(0) + 1)) COLOR 8, 0: PRINT CH$; END IF NEXT PCOPY 2, 0 RETURN END FUNCTION SUB SetMenuItemColor (Menu, Item, ForeColor, BackColor) MenuItems(Menu, Item).ForeColor = ForeColor MenuItems(Menu, Item).BackColor = BackColor END SUB