• Print

Author Topic: Ritchie's QB64 Menu Library V1.0 (Finished)  (Read 2077 times)

small no more

  • Sr. Member
  • ****
  • Posts: 251
  • Ask and you will receive, Seek and you will find
    • not launched
Re: Ritchie's QB64 Menu Library V1.0 (Finished)
« Reply #15 on: August 22, 2012, 04:06:20 PM »
Hello

TerryRitchie

This is in reference to this link
http://www.qb64.net/forum/index.php?topic=6918.0
A good teacher must be able to put himself in the place of those who find learning hard.


                                           Eliphas Levi

SMcNeill

  • Hero Member
  • *****
  • Posts: 2414
    • Email
Re: Ritchie's QB64 Menu Library V1.0 (Finished)
« Reply #16 on: September 14, 2012, 06:49:57 AM »
An update to Terry's library:  MAKEINPUTMENU

I added a new sub to the library which lets you input your menu from a text file instead of data statements.

Code: [Select]

SUB MAKEINPUTMENU (file$, foffset AS LONG)

'******************************************************************************
'* Creates the menu graphics for the menu system.
'*
'* Structure of menu entries:
'*
'* Menu entries must be put into DATA statements. For example:
'*
'* DATA "&File","&New#Ctrl+N","&Open#Ctrl+O","-&Save#Ctrl+S"
'* DATA "Save &as...#Ctrl+Shift+S","-E&xit#Ctrl+Q","*","!"
'*
'* Would create a new main menu entry called "File" and a submenu containing
'* "New", "Open", Save", "Save as..." and "Exit" appearing like so:
'*
'* +----+
'* |File|                        ID = 105 (1xx = first menu entry  )
'* |~   |                                 (x05 = 5 sub menu entries)
'* +----+--------------------+
'* | New              Ctrl+N |   ID = 1 (returned as 101)
'* | ~                       |
'* | Open             Ctrl+O |   ID = 2 (returned as 102)
'* | ~                       |                .
'* | ------------------------|                .
'* | Save             Ctrl+S |   ID = 3       .
'* | ~                       |                .
'* | Save as... Ctrl+Shift+S |   ID = 4       .
'* |      ~                  |                .
'* | ------------------------|                .
'* | Exit             Ctrl+Q |   ID = 5 (returned as 105)
'* |  ~                      |
'* +-------------------------+
'*
'* Symbols used:
'*
'* "-" - placing a dash at beginning places a line above this entry
'* "#" - text will be right justified
'* "&" - the following letter is the ALT key combination (underline)
'* "*" - denotes end of submenu entries   (must be alone)
'* "!" - denotes end of main menu entries (must be alone)
'*
'* Hotkey combinations following the "#" symbol will automatically be
'* deciphered, but the only key seperators allowed are the "+" plus symbol
'* and " " space. The following are valid:
'*
'* #Ctrl+X   #CTRLX   #Ctrl X   #ctrlx   #ctrl+x   #CTRL+ X   etc..
'*
'* The following names (upper, lower or any combination of case) can be used
'* for special keys:
'*
'* F1, F2 ... F12, CTRL, SHIFT, DEL, DELETE, INS, INSERT, HOME, END
'* PGUP, PAGEUP, PAGE UP, PGDN, PAGEDOWN, PAGE DOWN, UP, UPARROW, UP ARROW
'* DOWN, DOWNARROW, DOWN ARROW, RIGHT, RIGHTARROW, RIGHT ARROW, LEFT
'* LEFTARROW, LEFT ARROW, SCROLL, SLOCK, SCROLLLOCK, SCROLL LOCK, CAPS
'* CLOCK, CAPSLOCK, CAPS LOCK, NLOCK, NUMLOCK, NUM LOCK
'*
'******************************************************************************

DIM Count%
DIM x%
DIM MainMenu%
DIM SubMenu%
DIM MaxSubMenu%
DIM Selected$
DIM Length1%
DIM Length2%
DIM MaxLength1%
DIM MaxLength2%
DIM ReadData$
DIM Plus%
DIM Space%
DIM Rjustify$
DIM ScreenWidth%
DIM FontHold&
DIM DestHold&

REDIM MaxLength%(0)
REDIM TotalSubmenu%(0)
SHARED Menu() AS MENU
SHARED Mset AS MENUSETTINGS

'******************************************************************************
'* Set default values if not set by programmer. These defaults will set up a  *
'* generic menu with the standard Windows look and feel to it.                *
'******************************************************************************
IF (Mset.called AND 1) = 0 THEN Mset.font = _FONT(0)
IF (Mset.called AND 2) = 0 THEN SETMAINMENUCOLORS _RGB32(0, 0, 0), _RGB32(0, 0, 0), _RGB32(0, 0, 0), _RGB32(212, 208, 200), _RGB32(212, 208, 200), _RGB32(212, 208, 200)
IF (Mset.called AND 4) = 0 THEN
    IF Mset.sm3D THEN
        SETSUBMENUCOLORS _RGB32(0, 0, 0), _RGB32(0, 0, 0), _RGB32(128, 128, 128), _RGB32(128, 128, 128), _RGB32(212, 208, 200), _RGB32(212, 208, 200), _RGB32(212, 208, 200), _RGB32(212, 208, 200)
    ELSE
        SETSUBMENUCOLORS _RGB32(0, 0, 0), _RGB32(255, 255, 255), _RGB32(128, 128, 128), _RGB32(128, 128, 128), _RGB32(212, 208, 200), _RGB32(10, 36, 106), _RGB32(212, 208, 200), _RGB32(10, 36, 106)
    END IF
END IF
IF (Mset.called AND 8) = 0 THEN SETMENU3D 0, -1, -1, 0
IF (Mset.called AND 16) = 0 THEN SETMENUHEIGHT _FONTHEIGHT(Mset.font) + 8
IF (Mset.called AND 32) = 0 THEN SETMENUSPACING 10
IF (Mset.called AND 64) = 0 THEN SETMENUINDENT 0
IF (Mset.called AND 128) = 0 THEN SETMENUTEXT 1
IF (Mset.called AND 256) = 0 THEN SETMENUUNDERSCORE -1
IF (Mset.called AND 512) = 0 THEN SETSUBMENULOCATION 0
IF (Mset.called AND 1024) = 0 THEN SETMENUSHADOW 5

ScreenWidth% = _WIDTH(_DEST) '                                                 get the width of the current screen
DestHold& = _DEST '                                                            remember the calling destination
FontHold& = _FONT(_DEST) '                                                     remember the font used when entering this routine
_FONT Mset.font '                                                              set the font used for menu entries

'******************************************************************************
'* Scan the menu DATA to get menu and submenu sizing to create menu array     *
'******************************************************************************
f = FREEFILE
OPEN file$ FOR INPUT AS #f
SEEK #f, foffset
MainMenu% = 0 '                                                                reset main menu entry counter
MaxSubMenu% = 0 '                                                              reset maximum submenus seen
INPUT #f, ReadData$ '                                                               first entry must be main menu entry
DO WHILE ReadData$ <> "!" '                                                    stop looping when encountered
    MainMenu% = MainMenu% + 1 '                                                increment main menu entry counter
    INPUT #f, ReadData$ '                                                           second entry must be sub menu entry
    SubMenu% = 0 '                                                             reset sub menu entry counter
    MaxLength1% = 0 '                                                          reset max length of left text seen
    MaxLength2% = 0 '                                                          reset max length right justified text seen
    DO WHILE ReadData$ <> "*" '                                                stop looping when encountered
        SubMenu% = SubMenu% + 1 '                                              increment sub menu entry counter
        Length1% = 0 '                                                         reset length of left text seen
        Length2% = 0 '                                                         reset length of right justified text seen
        '**********************************************************************
        '* strip away all special formatting characters to reveal text only   *
        '**********************************************************************
        IF INSTR(ReadData$, "-") THEN ReadData$ = RIGHT$(ReadData$, LEN(ReadData$) - 1)
        IF INSTR(ReadData$, "&") THEN ReadData$ = LEFT$(ReadData$, INSTR(ReadData$, "&") - 1) + RIGHT$(ReadData$, LEN(ReadData$) - INSTR(ReadData$, "&"))
        IF INSTR(ReadData$, "#") THEN
            '******************************************************************
            '* get the length of left and right justified text and spacing    *
            '******************************************************************
            Length1% = _PRINTWIDTH(LEFT$(ReadData$, INSTR(ReadData$, "#") - 1)) + Mset.spacing * 2
            Length2% = _PRINTWIDTH(RIGHT$(ReadData$, LEN(ReadData$) - INSTR(ReadData$, "#"))) + Mset.spacing
        ELSE
            Length1% = _PRINTWIDTH(ReadData$) + Mset.spacing * 2
        END IF
        IF Length1% > MaxLength1% THEN MaxLength1% = Length1% '                remember the maximum left text seen
        IF Length2% > MaxLength2% THEN MaxLength2% = Length2% '                remember the maximum right justified text seen
        INPUT #f, ReadData$ '                                                       read next sub menu entry
    LOOP
    IF SubMenu% > MaxSubMenu% THEN MaxSubMenu% = SubMenu% '                    save the largest number of sub menu entries seen
    REDIM _PRESERVE MaxLength%(MainMenu%) '                                    increase submenu max length array
    MaxLength%(MainMenu%) = MaxLength1% + MaxLength2% '                        save maximum submenu entry length for this submenu
    REDIM _PRESERVE TotalSubmenu%(MainMenu%) '                                 increase submenu entry counter
    TotalSubmenu%(MainMenu%) = SubMenu% '                                      save nnumber of submenu entries seen for this submenu
    INPUT #f, ReadData$ '                                                           read next main menu entry
LOOP
REDIM Menu(MainMenu%, MaxSubMenu%) AS MENU '                                   resize the menu entry array accordingly
SEEK #f, foffset '                                                                      restore the DATA to be read in again
x% = Mset.indent
MainMenu% = 0 '                                                                reset main menu entry counter
SubMenu% = 0 '                                                                 reset submenu entry counter
Mset.centered = (Mset.height - _FONTHEIGHT(Mset.font)) \ 2 - 1 '               centered location of text on main/submenu entries
INPUT #f, ReadData$ '                                                               first entry must be main menu entry
DO WHILE ReadData$ <> "!" '                                                    stop looping when encountered
    MainMenu% = MainMenu% + 1 '                                                increment main menu entry counter
    AltKey% = INSTR(ReadData$, "&")
    IF AltKey% THEN
        Menu(MainMenu%, 0).altkey = RIGHTALTKEY + ASC(UCASE$(ReadData$), AltKey% + 1)
        Menu(MainMenu%, 0).altkeycharacter = ASC(UCASE$(ReadData$), AltKey% + 1)
        ReadData$ = LEFT$(ReadData$, AltKey% - 1) + RIGHT$(ReadData$, LEN(ReadData$) - AltKey%)
        Menu(MainMenu%, 0).altkeyx = _PRINTWIDTH(LEFT$(ReadData$, AltKey% - 1))
        Menu(MainMenu%, 0).altkeywidth = _PRINTWIDTH(MID$(ReadData$, AltKey%, 1)) - 2
    END IF
    Menu(MainMenu%, 0).text = ReadData$ '                                      yes, save the main menu entry
    Menu(MainMenu%, 0).idnum = MainMenu% * 100 '                               save the main menu entry id number (hundreds place)
    Menu(MainMenu%, 0).width = _PRINTWIDTH(ReadData$) + Mset.spacing * 2 '                             width of main menu entry
    Mset.width = Mset.width + Menu(MainMenu%, 0).width '                                           main menu total width
    Menu(MainMenu%, 0).x = x% '                                                                    left location of main entry box
    Menu(MainMenu%, 0).active = _NEWIMAGE(Menu(MainMenu%, 0).width, Mset.height, 32) '             active main menu entry image (normal)
    _DEST Menu(MainMenu%, 0).active
    _FONT Mset.font
    _PRINTMODE _KEEPBACKGROUND
    Menu(MainMenu%, 0).highlight = _NEWIMAGE(Menu(MainMenu%, 0).width, Mset.height, 32) '          highlighted main menu entry image (mouse over)
    _DEST Menu(MainMenu%, 0).highlight
    _FONT Mset.font
    _PRINTMODE _KEEPBACKGROUND
    Menu(MainMenu%, 0).selected = _NEWIMAGE(Menu(MainMenu%, 0).width, Mset.height, 32) '           selected main menu entry image (left clicked)
    _DEST Menu(MainMenu%, 0).selected
    _FONT Mset.font
    _PRINTMODE _KEEPBACKGROUND
    Menu(MainMenu%, 0).submenu = _NEWIMAGE(MaxLength%(MainMenu%) + 4, (TotalSubmenu%(MainMenu%)) * Mset.height + 4, 32)
    _DEST Menu(MainMenu%, 0).submenu
    _FONT Mset.font
    _PRINTMODE _KEEPBACKGROUND
    Menu(MainMenu%, 0).undersubmenu = _NEWIMAGE(MaxLength%(MainMenu%) + 4 + Mset.shadow, (TotalSubmenu%(MainMenu%)) * Mset.height + 4 + Mset.shadow, 32)
    _DEST Menu(MainMenu%, 0).undersubmenu
    _FONT Mset.font
    _PRINTMODE _KEEPBACKGROUND
    SubMenu% = 0 '                                                                                 reset sub menu entry counter
    input #f, ReadData$ '                                                                               second entry must be sub menu entry
    DO WHILE ReadData$ <> "*" '                                                                    stop looping when encountered
        SubMenu% = SubMenu% + 1 '                                                                  increment sub menu entry counter
        Menu(MainMenu%, SubMenu%).text = ReadData$ '                                               yes, save the sub menu entry
        Menu(MainMenu%, SubMenu%).idnum = SubMenu% '                                               save the sub menu entry id number (1-99)
        Menu(MainMenu%, SubMenu%).width = MaxLength%(MainMenu%) '                                  width of submenu entry
        Menu(MainMenu%, SubMenu%).x = 2 '                                                          x location of submenu entry
        Menu(MainMenu%, SubMenu%).y = ((SubMenu% - 1) * Mset.height) + 2 '                         y location of submenu entry
        Menu(MainMenu%, SubMenu%).active = _NEWIMAGE(MaxLength%(MainMenu%), Mset.height, 32) '     active (normal) submenu entry image
        _DEST Menu(MainMenu%, SubMenu%).active
        _FONT Mset.font
        _PRINTMODE _KEEPBACKGROUND
        Menu(MainMenu%, SubMenu%).highlight = _NEWIMAGE(MaxLength%(MainMenu%), Mset.height, 32) '  highlighted submenu entry image
        _DEST Menu(MainMenu%, SubMenu%).highlight
        _FONT Mset.font
        _PRINTMODE _KEEPBACKGROUND
        Menu(MainMenu%, SubMenu%).inactive = _NEWIMAGE(MaxLength%(MainMenu%), Mset.height, 32) '   inactive (disabled) submenu entry image
        _DEST Menu(MainMenu%, SubMenu%).inactive
        _FONT Mset.font
        _PRINTMODE _KEEPBACKGROUND
        Menu(MainMenu%, SubMenu%).ihighlight = _NEWIMAGE(MaxLength%(MainMenu%), Mset.height, 32) ' inactive (disabled) highlighted submenu entry image
        _DEST Menu(MainMenu%, SubMenu%).ihighlight
        _FONT Mset.font
        _PRINTMODE _KEEPBACKGROUND
        Menu(MainMenu%, SubMenu%).live = -1 '                                                      submenu entry enabled by default
        IF INSTR(ReadData$, "-") THEN '                                                            should this entry have a line above?
            IF SubMenu% > 1 THEN Menu(MainMenu%, SubMenu%).drawline = -1 '                        yes, remember this
            ReadData$ = RIGHT$(ReadData$, LEN(ReadData$) - 1) '                                        remove the dash
        END IF
        AltKey% = INSTR(ReadData$, "&") '                                                             find an alt key marker
        IF AltKey% THEN '                                                                             found?
            Menu(MainMenu%, SubMenu%).altkey = RIGHTALTKEY + ASC(UCASE$(ReadData$), AltKey% + 1) '    yes, save the alt key combo value
            Menu(MainMenu%, SubMenu%).altkeycharacter = ASC(UCASE$(ReadData$), AltKey% + 1) '         save the actual alt key
            ReadData$ = LEFT$(ReadData$, AltKey% - 1) + RIGHT$(ReadData$, LEN(ReadData$) - AltKey%) ' remove the alt key marker
            Menu(MainMenu%, SubMenu%).altkeyx = _PRINTWIDTH(LEFT$(ReadData$, AltKey% - 1)) '          remember position of alt underline
            Menu(MainMenu%, SubMenu%).altkeywidth = _PRINTWIDTH(MID$(ReadData$, AltKey%, 1)) - 2 '    remember how wide the underline is
        END IF
        IF INSTR(ReadData$, "#") THEN '                                                                      is there a hot key marker?
            Menu(MainMenu%, SubMenu%).ljustify = LEFT$(ReadData$, INSTR(ReadData$, "#") - 1) '               yes, get left submenu text
            Menu(MainMenu%, SubMenu%).rjustify = RIGHT$(ReadData$, LEN(ReadData$) - INSTR(ReadData$, "#")) ' get hotkey right justified text
            '******************************************
            '* Attempt to discover hotkey combination *
            '******************************************
            Rjustify$ = UCASE$(RTRIM$(Menu(MainMenu%, SubMenu%).rjustify))
            WHILE INSTR(Rjustify$, "+") OR INSTR(Rjustify$, " ")
                Plus% = INSTR(Rjustify$, "+")
                IF Plus% THEN Rjustify$ = LEFT$(Rjustify$, Plus% - 1) + RIGHT$(Rjustify$, LEN(Rjustify$) - Plus%)
                Space% = INSTR(Rjustify$, " ")
                IF Space% THEN Rjustify$ = LEFT$(Rjustify$, Space% - 1) + RIGHT$(Rjustify$, LEN(Rjustify$) - Space%)
            WEND
            IF INSTR(Rjustify$, "CTRL") THEN
                Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 100305 ' ** Right CTRL Key
                Rjustify$ = LEFT$(Rjustify$, INSTR(Rjustify$, "CTRL") - 1) + RIGHT$(Rjustify$, LEN(Rjustify$) - (INSTR(Rjustify$, "CTRL") + 3))
            END IF
            IF INSTR(Rjustify$, "SHIFT") THEN
                Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 100303 ' ** Right SHIFT key
                Rjustify$ = LEFT$(Rjustify$, INSTR(Rjustify$, "SHIFT") - 1) + RIGHT$(Rjustify$, LEN(Rjustify$) - (INSTR(Rjustify$, "SHIFT") + 4))
            END IF
            SELECT CASE Rjustify$
                CASE "F1"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 15104 ' ** F1 Key
                CASE "F2"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 15360 ' ** F2 Key
                CASE "F3"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 15616 ' ** F3 Key
                CASE "F4"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 15872 ' ** F4 Key
                CASE "F5"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 16128 ' ** F5 Key
                CASE "F6"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 16384 ' ** F6 Key
                CASE "F7"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 16640 ' ** F7 Key
                CASE "F8"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 16896 ' ** F8 Key
                CASE "F9"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 17152 ' ** F9 Key
                CASE "F10"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 17408 ' ** F10 Key
                CASE "F11"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 34048 ' ** F11 Key
                CASE "F12"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 34304 ' ** F12 Key
                CASE "DEL", "DELETE"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 21248 ' ** DELETE Key
                CASE "INS", "INSERT"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 20992 ' ** INSERT Key
                CASE "HOME"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 18176 ' ** HOME Key
                CASE "END"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 20224 ' ** END Key
                CASE "PGUP", "PAGEUP"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 18688 ' ** PGUP Key
                CASE "PGDN", "PAGEDOWN"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 20736 ' ** PGDN Key
                CASE "RIGHT", "RIGHTARROW"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 19712 ' ** Right Arrow Key (use?)
                CASE "LEFT", "LEFTARROW"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 19200 ' ** Left Arrow Key  (use?)
                CASE "UP", "UPARROW"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 18432 ' ** Up Arrow Key    (use?)
                CASE "DOWN", "DOWNARROW"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 20480 ' ** Down Arrow Key  (use?)
                CASE "CLOCK", "CAPS", "CAPSLOCK"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 100301 ' ** CAPS Lock Key
                CASE "NLOCK", "NUM", "NUMLOCK"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 100300 ' ** NUM Lock Key
                CASE "SLOCK", "SCROLL", "SCROLLLOCK"
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + 100302 ' ** SCROLL Lock Key
                CASE ELSE
                    Menu(MainMenu%, SubMenu%).hotkey = Menu(MainMenu%, SubMenu%).hotkey + ASC(Rjustify$) ' ** any other key
            END SELECT
        ELSE
            Menu(MainMenu%, SubMenu%).ljustify = ReadData$ '                   left text
            Menu(MainMenu%, SubMenu%).rjustify = "" '                          no hotkey
        END IF
        input #f, ReadData$ '                                                       read next sub menu entry
    LOOP
    Menu(MainMenu%, 0).idnum = Menu(MainMenu%, 0).idnum + SubMenu% '           attach the number of sub menu entries to main id number
    x% = x% + Menu(MainMenu%, 0).width '                                       move to next main menu position
    input #f, ReadData$ '                                                           read next main menu entry
LOOP
Mset.menubar = _NEWIMAGE(ScreenWidth%, Mset.height, 32) '                          create normal menu bar image
_DEST Mset.menubar '                                                               set it as the destination image
_FONT Mset.font '                                                              set its font
_PRINTMODE _KEEPBACKGROUND '                                                   set its font behavior
Mset.menubarhighlight = _NEWIMAGE(ScreenWidth%, Mset.height, 32) '                 create higlighted menu bar image
_DEST Mset.menubarhighlight '                                                      set it as the destination image
_FONT Mset.font '                                                              set its font
_PRINTMODE _KEEPBACKGROUND '                                                   set its font behavior
Mset.menubarselected = _NEWIMAGE(ScreenWidth%, Mset.height, 32) '                  create selected menu bar image
_DEST Mset.menubarselected '                                                       set it as the destination image
_FONT Mset.font '                                                              set its font
_PRINTMODE _KEEPBACKGROUND '                                                   set its font behavior
Mset.undermenu = _NEWIMAGE(ScreenWidth%, Mset.height, 32)

'******************************************************************************
'* Draw all the menu graphics                                                 *
'******************************************************************************
DrawMenuBars
FOR MainMenu% = 1 TO UBOUND(Menu)
    DrawMainEntry MainMenu%
    DrawSubMenu MainMenu%
    FOR SubMenu% = 1 TO Menu(MainMenu%, 0).idnum - ((Menu(MainMenu%, 0).idnum \ 100) * 100)
        DrawSubEntry MainMenu%, SubMenu%
    NEXT SubMenu%
NEXT MainMenu%
'******************************************************************************
'* routine cleanup                                                            *
'******************************************************************************
REDIM MaxLength%(0) '                                                          array no longer needed, free memory
REDIM TotalSubmenu%(0) '                                                       array no longer needed, free memory
_FREEIMAGE Mset.menubarhighlight '                                                 image no longer needed, free memory
_FREEIMAGE Mset.menubarselected '                                                  image no longer needed, free memory
_DEST DestHold& '                                                              restore original destination when routine called
_FONT FontHold& '                                                              restore original font when routine called
CLOSE f
END SUB

The way this works is you make a CSV text file, set up just as as you would the DATA statements.   Then call the routine with the filename and offset.  (NOTE:  Offset is NOT optional.  Without it, you will error out.)

Use is like this:   MAKEINPUTMENU file$,offset

If your data is in one file, the offset will be 1, not 0.   We seek to the first byte in a file, not the 0th byte.

The reason I put an offset into the routine is so that you can use one menu.txt file for several different menus.  Set the offset to the point where the data starts in the text file.  I didn't post it as an updated library, since this is Terry's project.  It'll be up to him if he wants to include it into his main library.  ;) 

NOTE:  By using foffset as LONG, we can seek to 2,147,483,647 bytes in a file.  If for some reason you need to seek deeper into a file for your menu, or your file is larger than 2GB, change this to _INTEGER64 or _UNSIGNED INTEGER64 to seek up to 18,446,744,073,709,551,615 bytes deep.   Any deeper than that, just start a new file for your menu....   
« Last Edit: September 14, 2012, 01:15:45 PM by SMcNeill »
http://bit.ly/TextImage -- Library of QB64 code to manipulate text and images, as a BM library.
http://bit.ly/Color32 -- A set of color CONST for use in 32 bit mode, as a BI library.

http://bit.ly/DataToDrive - A set of routines to quickly and easily get data to and from the disk.  BI and BM files

SMcNeill

  • Hero Member
  • *****
  • Posts: 2414
    • Email
Re: Ritchie's QB64 Menu Library V1.0 (Finished)
« Reply #17 on: September 16, 2012, 08:12:26 AM »
An easy way to use arrays to make menus:

Code: [Select]
SUB MAKEARRAYMENU (array() AS STRING)
'Our zero elements aren't used in our array, so we're going to make use of them here.
'array(0,0) = our max number of columns
'array(0,1) = our max number of rows

'open a temp menu file on the hard drive, and write our array there.
file$ = "TempJunkMenuFile.mnu"
f = FREEFILE
OPEN file$ FOR OUTPUT AS #f
FOR i = 1 TO VAL(array(0, 0))
    FOR j = 0 TO VAL(array(0, 1))
        IF array(i, j) <> "" THEN WRITE #1, array(i, j),
NEXT j, i
CLOSE f

'make a menu from the temp file
MAKEINPUTMENU file$, 1

'clean up the temp file
KILL file$
END SUB

This little routine goes with the previous one, and all it does is simply write an array to the disk in the format which we need to use to read it back into a menu with the previous routine.

Take both and copy them into the Menu.BI file and save them.  Then copy the following code and give it a run:
Code: [Select]
'$INCLUDE:'menutop.bi'

CONST FALSE = 0, TRUE = NOT FALSE
DIM Menu%
DIM menuarray(2, 4) AS STRING
SCREEN _NEWIMAGE(640, 480, 32)
CLS , _RGB32(50, 100, 200)
_SCREENMOVE _MIDDLE

menuarray(0, 0) = "2"
menuarray(0, 1) = "4"

menuarray(1, 0) = "&File"
menuarray(1, 1) = "&Open...#CTRL+O"
menuarray(1, 2) = "&Save#CTRL+S"
menuarray(1, 3) = "-E&xit#CTRL+Q"
menuarray(1, 4) = "*"

menuarray(2, 0) = "&Help"
menuarray(2, 1) = "&About"
menuarray(2, 2) = "*"
menuarray(2, 3) = "!"

MAKEARRAYMENU menuarray()
SHOWMENU
DO
    Menu% = CHECKMENU%(TRUE)
LOOP UNTIL Menu% = 103
HIDEMENU

'$INCLUDE:'menu.bi'

Notice, we use the 0,0 and 0,1 element of our array to define how many columns and rows we're going to have.  After that, we set it up EXACTLY like we would in the data statements.  (Compare this little sample to Terry's Sample1.bas to see for yourself.)  Use "*" for the last element in your columns, and "!" as an EndOfData code.  No need to worry about unused elements -- the routine ignores blank fields ("").

There's probably more efficient and quicker ways to pull off both of these routines, but this seems the simplest way to me.  (And honestly, who's concerned over a half second making a menu?  You do it once, and then it's more or less done.  It's not like moving a character across the screen while shooting...)

Many thanks to Terry for a very nice menu program!  I hope he doesn't mind me playing around under the hood and tinkering with it a little bit.  ;)

I'm not the world's biggest fan of DATA statements, and arrays work MUCH better for me usually.  I just figured if I was going to tinker to make it work for me, I'd share and maybe someone else could get a little service from the add-ons as well.  Any questions, thoughts, or problems feel free to mention and I'll address them if I can.  :)
http://bit.ly/TextImage -- Library of QB64 code to manipulate text and images, as a BM library.
http://bit.ly/Color32 -- A set of color CONST for use in 32 bit mode, as a BI library.

http://bit.ly/DataToDrive - A set of routines to quickly and easily get data to and from the disk.  BI and BM files

TerryRitchie

  • Hero Member
  • *****
  • Posts: 2264
  • FORMAT C:\ /Q /U /AUTOTEST (How to repair Win8)
    • Email
Re: Ritchie's QB64 Menu Library V1.0 (Finished)
« Reply #18 on: September 16, 2012, 08:24:37 AM »
Quote
Many thanks to Terry for a very nice menu program!  I hope he doesn't mind me playing around under the hood and tinkering with it a little bit.

Heck no! This is GOOD stuff! I'm always happy to see others improve/update/add to my code.  When I get time I am going to incorporate your ideas into the next version of the library.

I wasn't thrilled with sticking with DATA statements either, but I saw it as the quickest way for me to finish the library since school was starting soon.  I'm happy that you have taken up improving the code.  Thank you. :)

Clippy

  • Hero Member
  • *****
  • Posts: 16440
  • I LOVE π = 4 * ATN(1)    Use the QB64 WIKI >>>
    • Pete's Qbasic Site
    • Email
Re: Ritchie's QB64 Menu Library V1.0 (Finished)
« Reply #19 on: September 16, 2012, 08:27:32 AM »
Often DATA statements can be made from CSV files and vice-versa. The way you supply data is up to the designer.
QB64 WIKI: Main Page
Download Q-Basics Code Demo: Q-Basics.zip
Download QB64 BAT, IconAdder and VBS shortcuts: QB64BAT.zip
Download QB64 DLL files in a ZIP: Program64.zip

Kopecjay

  • Full Member
  • ***
  • Posts: 104
Re: Ritchie's QB64 Menu Library V1.0 (Finished)
« Reply #20 on: September 16, 2012, 08:29:49 AM »
Neat, I 've been thinking of using this menu library soon and this makes it even more attractive.

TerryRitchie

  • Hero Member
  • *****
  • Posts: 2264
  • FORMAT C:\ /Q /U /AUTOTEST (How to repair Win8)
    • Email
Re: Ritchie's QB64 Menu Library V1.0 (Finished)
« Reply #21 on: September 16, 2012, 08:33:05 AM »
Quote from: Kopecjay on September 16, 2012, 08:29:49 AM
Neat, I 've been thinking of using this menu library soon and this makes it even more attractive.

Yes, it does!

For those interested in the library you definitely need to check out SMcNeill's additions/improvements to the code.

SMcNeill

  • Hero Member
  • *****
  • Posts: 2414
    • Email
Re: Ritchie's QB64 Menu Library V1.0 (Finished)
« Reply #22 on: September 16, 2012, 09:07:54 AM »
A quick change to our 2nd routine to make its use even simpler:

Code: [Select]
SUB MAKEARRAYMENU (array() AS STRING)

'open a temp menu file on the hard drive, and write our array there.
file$ = "TempJunkMenuFile.mnu"
f = FREEFILE
OPEN file$ FOR OUTPUT AS #f
FOR i = 1 TO UBOUND(array,1)
    FOR j = 0 TO UBOUND(array, 2)
        IF array(i, j) <> "" THEN WRITE #f, array(i, j),
NEXT j
WRITE #f, "*"
NEXT i
WRITE #f, "!"
CLOSE f

'make a menu from the temp file
MAKEINPUTMENU file$, 1

'clean up the temp file
KILL file$
END SUB

There's honestly no reason why we have to use the zero elements to tell our routine how big the array is  -- we have a command for that.   By setting it to the UBOUND limit, we eliminate the need for array(0,0) and array(0,1).  We also automate the end of line and end of data statements so we don't need them in our array.

Make the change, and try the following:
Code: [Select]
'$INCLUDE:'menutop.bi'

CONST FALSE = 0, TRUE = NOT FALSE
DIM Menu%
DIM menuarray(2, 4) AS STRING
SCREEN _NEWIMAGE(640, 480, 32)
CLS , _RGB32(50, 100, 200)
_SCREENMOVE _MIDDLE

menuarray(1, 0) = "&File"
menuarray(1, 1) = "&Open...#CTRL+O"
menuarray(1, 2) = "&Save#CTRL+S"
menuarray(1, 3) = "-E&xit#CTRL+Q"

menuarray(2, 0) = "&Help"
menuarray(2, 1) = "&About"

MAKEARRAYMENU menuarray()
SHOWMENU
DO
    Menu% = CHECKMENU%(TRUE)
LOOP UNTIL Menu% = 103
HIDEMENU

'$INCLUDE:'menu.bi'

Any time I can reduce the amount of code required to do something, without harming its ability to function, it's a good thing.  :D

Use this for MAKEARRAYMENU instead of the other version.  It's less work, and less prone to user error (harder to swap the values this way, and it auto-generates its own special characters).

Like this, all we need for our array is the elements we actually need for our array.  ;)

http://bit.ly/TextImage -- Library of QB64 code to manipulate text and images, as a BM library.
http://bit.ly/Color32 -- A set of color CONST for use in 32 bit mode, as a BI library.

http://bit.ly/DataToDrive - A set of routines to quickly and easily get data to and from the disk.  BI and BM files

Clippy

  • Hero Member
  • *****
  • Posts: 16440
  • I LOVE π = 4 * ATN(1)    Use the QB64 WIKI >>>
    • Pete's Qbasic Site
    • Email
Re: Ritchie's QB64 Menu Library V1.0 (Finished)
« Reply #23 on: September 16, 2012, 09:15:15 AM »
CONST FALSE = 0, TRUE = NOT FALSE

Save a few more bytes:

CONST FALSE = 0, TRUE = -1
QB64 WIKI: Main Page
Download Q-Basics Code Demo: Q-Basics.zip
Download QB64 BAT, IconAdder and VBS shortcuts: QB64BAT.zip
Download QB64 DLL files in a ZIP: Program64.zip

SMcNeill

  • Hero Member
  • *****
  • Posts: 2414
    • Email
Re: Ritchie's QB64 Menu Library V1.0 (Finished)
« Reply #24 on: September 16, 2012, 09:58:49 AM »
A quick demo of using the 2 routines I posted to make multiple menus for a program:

Copy both routines (MAKEINPUTMENU and the 2nd MAKEARRAYMENU) into Terry's Menu.BI library.  Then run this code through QB64:

Code: [Select]
'$INCLUDE:'menutop.bi'

CONST FALSE = 0, TRUE = NOT FALSE
DIM Menu%
DIM menuarray(2, 3) AS STRING
SCREEN _NEWIMAGE(640, 480, 32)
CLS , _RGB32(50, 100, 200)
_SCREENMOVE _MIDDLE

menuarray(1, 0) = "&File"
menuarray(1, 1) = "&Open...#CTRL+O"
menuarray(1, 2) = "&Save#CTRL+S"
menuarray(1, 3) = "-E&xit Blandsville #CTRL+Q"

menuarray(2, 0) = "&Help"
menuarray(2, 1) = "&About"

MAKEARRAYMENU menuarray()
SHOWMENU
DO
    Menu% = CHECKMENU%(TRUE)
LOOP UNTIL Menu% = 103
HIDEMENU

menuarray(1, 0) = "&Hello World"
menuarray(1, 1) = "&Dance"
menuarray(1, 2) = "&Giggle"
menuarray(1, 3) = "-G&oodbye World"

menuarray(2, 0) = "&Help"
menuarray(2, 1) = "&About"

MAKEARRAYMENU menuarray()
SHOWMENU
DO
    Menu% = CHECKMENU%(TRUE)
LOOP UNTIL Menu% = 103
HIDEMENU

'$INCLUDE:'menu.bi'

Terry's routines let us make pretty menus.  These little changes let us make multiple menus, as needed, for our program.  Like this, we can use toggles in our menus (Spellcheck ON... click it, and the menu could then say Spellcheck OFF...), or completely different menus.  It doesn't change Terry's work, all it does is add a new layer of possibilities to what he's already accomplished.  ;)

NOTE:  One thing to be aware of though -- Our hotkeys will change as the menu changes.  The first menu uses Alt-S as a save file hotkey.  The second one doesn't preserve that function at all.  We could assign Alt-S to a SLEEP command on the 2nd menu if we wanted.   If you want a set of hotkeys to be constant though-out your program, you'll need to key them in differently than through the menu function.  Menu will just reserve the keys that it has currently defined, and that changes as the menu changes.
http://bit.ly/TextImage -- Library of QB64 code to manipulate text and images, as a BM library.
http://bit.ly/Color32 -- A set of color CONST for use in 32 bit mode, as a BI library.

http://bit.ly/DataToDrive - A set of routines to quickly and easily get data to and from the disk.  BI and BM files

SMcNeill

  • Hero Member
  • *****
  • Posts: 2414
    • Email
Re: Ritchie's QB64 Menu Library V1.0 (Finished)
« Reply #25 on: September 16, 2012, 03:49:36 PM »
Terry, I went in and did some variable changes throughout your library for compatibility reasons.  One thing I use almost all the time is my little Color32.BI library.  It's simple, but it auto-defines a lot of RGB32 colors for ease of use and consistency.  I use colors like Red, White, Green, Black, CrayolaBlue -- it's a whole list of them.  :)

Unfortunately, they didn't want to work with your menu library.  There's places in the code with Red%, Green%, Blue% as variables, and QB64 won't allow them with Red, Green, Blue defined as CONST.   (Which I find odd, since Red, Red%, Red~% are all valid and different variables allowed.  Use a CONST for one of them, and you reject all of them...)

So what I've did is go in and change these from Red%, Green%, Blue% to MenuRed%, MenuGreen%, MenuBlue%, so that they'll work and not conflict with each other.  I'll upload the altered BI file here for you, and I hope you'll use it with these minor changes as you update your code in the future.  I'm certain if I use a CONST Red = &HFFFF0000, there's other people who will as well, but MenuRed is a lot less likely to be reserved in such a manner.  ;)

Altered code is attached as Menu2.BI, so you can look over the changes and see if they're something you don't mind keeping.  It's a minor thing, but I hope you'll consider keeping the changes for future versions.  :D

http://bit.ly/TextImage -- Library of QB64 code to manipulate text and images, as a BM library.
http://bit.ly/Color32 -- A set of color CONST for use in 32 bit mode, as a BI library.

http://bit.ly/DataToDrive - A set of routines to quickly and easily get data to and from the disk.  BI and BM files

Kopecjay

  • Full Member
  • ***
  • Posts: 104
Re: Ritchie's QB64 Menu Library V1.0 (Finished)
« Reply #26 on: September 24, 2012, 09:26:15 PM »
Hey,

Perhaps you 'll be proud to know I 've implemented your menu in my chess gui. Currently, it's the simplest implementation; almost a copy paste of your first example. I just wanted to compile for a friend and provide him with a familiar way to exit  :D. At least I seem to have gotten SHOWMENU's location correct. And I certainly hope to do more with it.

As an aside... my ide has started crashing while working on the code, ever since I included the menu. I 'm guessing it's because of the total size of the code? Either way it's first time this is happening.
« Last Edit: September 25, 2012, 11:46:21 AM by Kopecjay »

TerryRitchie

  • Hero Member
  • *****
  • Posts: 2264
  • FORMAT C:\ /Q /U /AUTOTEST (How to repair Win8)
    • Email
Re: Ritchie's QB64 Menu Library V1.0 (Finished)
« Reply #27 on: September 25, 2012, 01:50:57 PM »
It's always good to hear that my code is benefiting someone else. :)

The include files should not be crashing your IDE simply by including them.  Perhaps you've found a bug in my code that needs addressed? 
When the IDE crashes does it give you any kind of error message or reason for crashing?

Kopecjay

  • Full Member
  • ***
  • Posts: 104
Re: Ritchie's QB64 Menu Library V1.0 (Finished)
« Reply #28 on: September 25, 2012, 03:22:10 PM »
It's the good old 'qb64.exe has stopped working'. I have no problems running your example files, issue appears only when I include it in my already pretty large program. QB64 appears to check the entire code for validity after every single change and that seems to lead to trouble eventually. I guess I 'll have keep menu commands commented out while I work on the code.

small no more

  • Sr. Member
  • ****
  • Posts: 251
  • Ask and you will receive, Seek and you will find
    • not launched
Re: Ritchie's QB64 Menu Library V1.0 (Finished)
« Reply #29 on: January 18, 2013, 12:19:32 PM »
Is there a way to make the "HELP" Menu right justified like in qb64 IDE Menu
A good teacher must be able to put himself in the place of those who find learning hard.


                                           Eliphas Levi

  • Print