User Tools

Site Tools


allocating_20item_20ids_20automatically

Allocating item IDs automatically

by Michael Hutton, June 2010; amended by Richard Russell

Whenever menu items are created (and this also applies to controls within a dialog box for example) you must assign each of them a unique ID. For example:

        SYS "AppendMenu", hmenu%, 0, 100, "Menu Item&1"
        SYS "AppendMenu", hmenu%, 0, 101, "Menu Item&2"

Later in your program you will probably need to know the ID numbers of the menu items, for instance in a routine that responds to WM_COMMAND messages. It can be tedious and confusing to use a numeric value in this situation, and if you want to expand the menu things can get worse when the numbers are not in a logical order.

The traditional solution to this is to use named constants rather than numeric values, for example:

        MENUITEM1 = 100
        MENUITEM2 = 101
 
        SYS "AppendMenu", hmenu%, 0, MENUITEM1, "Menu Item&1"
        SYS "AppendMenu", hmenu%, 0, MENUITEM2, "Menu Item&2"

So long as the names of the constants are related to the functions of the menu items they will be easily remembered, and you can add extra items in any position without concern for the numeric sequence.

However if you have a large menu with many items, or a dialogue box with many controls, it may be helpful to automate the process of allocating ID values to each item/control. One way in which this may be done is to create a structure to store all the IDs for you and then use a 'trick' to automatically assign values to the structure elements.

To do this first create a structure, we will call it MENUID{}, although you can call it anything you want. It is important to make sure that every member is an integer (% suffix):

        DIM MENUID{                     \
        \           First{              \
        \                 FirstItem%,   \
        \                 SecondItem%,  \
        \                 ThirdItem% }, \
        \           Second{             \
        \                 FirstItem%,   \
        \                 SecondItem%,  \
        \                 ThirdItem% }, \
        \           Third{              \
        \                 FirstItem%,   \
        \                 SecondItem%,  \
        \                 ThirdItem% } }

Now, we use a few lines of code to iterate through the structure and assign a unique value to each member, in this case starting at 100:

        FOR I% = 0 TO DIM(MENUID{})-4 STEP 4
          !(MENUID{}+I%) = 100 + I%/4
        NEXT

Now we create our 'popup' menus and the main menu..

        MF_POPUP = &10
        WM_COMMAND = &111
 
        SYS "CreatePopupMenu" TO first%
        SYS "AppendMenu", first%, 0, MENUID.First.FirstItem%, "&First"
        SYS "AppendMenu", first%, 0, MENUID.First.SecondItem%, "&Second"
        SYS "AppendMenu", first%, 0, MENUID.First.ThirdItem%, "&Third"
 
        SYS "CreatePopupMenu" TO second%
        SYS "AppendMenu", second%, 0, MENUID.Second.FirstItem%, "&First"
        SYS "AppendMenu", second%, 0, MENUID.Second.SecondItem%, "&Second"
        SYS "AppendMenu", second%, 0, MENUID.Second.ThirdItem%, "&Third"
 
        SYS "CreatePopupMenu" TO third%
        SYS "AppendMenu", third%, 0, MENUID.Third.FirstItem%, "&First"
        SYS "AppendMenu", third%, 0, MENUID.Third.SecondItem%, "&Second"
        SYS "AppendMenu", third%, 0, MENUID.Third.ThirdItem%, "&Third"
 
        SYS "CreateMenu" TO hmenu%
        SYS "AppendMenu", hmenu%, MF_POPUP, first%, "&First"
        SYS "AppendMenu", hmenu%, MF_POPUP, second%, "&Second"
        SYS "AppendMenu", hmenu%, MF_POPUP, third%, "&Third"
        SYS "SetMenu", @hwnd%, hmenu%
        SYS "DrawMenuBar", @hwnd%
        VDU 26

And next we add our ON SYS handler and our main program loop:

        DIM Click%(2), click%(2)
        ON SYS Click%() = @msg%, @wparam%, @lparam% : RETURN
 
        REPEAT
          click%() = 0
          SWAP Click%(), click%()
 
          CASE click%(1) AND &FFFF OF
 
            WHEN MENUID.First.FirstItem%:
              SYS "MessageBox", @hwnd%, STR$(MENUID.First.FirstItem%), "Menu ID", 0
 
            WHEN MENUID.First.SecondItem%:
              SYS "MessageBox", @hwnd%, STR$(MENUID.First.SecondItem%), "Menu ID", 0
 
            WHEN MENUID.First.ThirdItem%:
              SYS "MessageBox", @hwnd%, STR$(MENUID.First.ThirdItem%), "Menu ID", 0
 
            WHEN MENUID.Second.FirstItem%:
              SYS "MessageBox", @hwnd%, STR$(MENUID.Second.FirstItem%), "Menu ID", 0
 
            WHEN MENUID.Second.SecondItem%:
              SYS "MessageBox", @hwnd%, STR$(MENUID.Second.SecondItem%), "Menu ID", 0
 
            WHEN MENUID.Second.ThirdItem%:
              SYS "MessageBox", @hwnd%, STR$(MENUID.Second.ThirdItem%), "Menu ID", 0
 
            WHEN MENUID.Third.FirstItem%:
              SYS "MessageBox", @hwnd%, STR$(MENUID.Third.FirstItem%), "Menu ID", 0
 
            WHEN MENUID.Third.SecondItem%:
              SYS "MessageBox", @hwnd%, STR$(MENUID.Third.SecondItem%), "Menu ID", 0
 
          ENDCASE
 
          WAIT 1
        UNTIL FALSE

You can now easily add menus or menu items by just adding to the MENUID structure. You could also add item IDs of any Dialog boxes you want. Here is an example program you can copy and paste into a BB4W IDE:

        REM Install our libraries
        INSTALL @lib$+"WINLIB2"
 
        REM Create our ID structure
        DIM ID{                \
        \     First{               \
        \           FirstItem%,    \
        \           SecondItem%,   \
        \           ThirdItem% },  \
        \     Second{              \
        \           FirstItem%,    \
        \           SecondItem%,   \
        \           ThirdItem% },  \
        \     Third{               \
        \           FirstItem%,    \
        \           SecondItem%,   \
        \           Square% },     \
        \     Square{              \
        \           Static1%,      \
        \           Static2%,      \
        \           InputEditbox%, \
        \           OutputEditbox%,\
        \           CalcButton%,   \
        \           CloseButton% } }
 
        REM Assign ID numbers to the elements
        FOR I% = 0 TO DIM(ID{})-4 STEP 4
          !(ID{}+I%) = 100 + I%/4
        NEXT
 
        REM Define some Windows constants
        REM!WC
        BS_DEFPUSHBUTTON = &1
        ES_READONLY = &800
        ES_NUMBER = &2000
        WM_COMMAND = &111
        MF_POPUP = &10
 
        REM Create our menus
        SYS "CreatePopupMenu" TO first%
        SYS "AppendMenu", first%, 0, ID.First.FirstItem%, "&First"
        SYS "AppendMenu", first%, 0, ID.First.SecondItem%, "&Second"
        SYS "AppendMenu", first%, 0, ID.First.ThirdItem%, "&Third"
 
        SYS "CreatePopupMenu" TO second%
        SYS "AppendMenu", second%, 0, ID.Second.FirstItem%, "&First"
        SYS "AppendMenu", second%, 0, ID.Second.SecondItem%, "&Second"
        SYS "AppendMenu", second%, 0, ID.Second.ThirdItem%, "&Third"
 
        SYS "CreatePopupMenu" TO third%
        SYS "AppendMenu", third%, 0, ID.Third.FirstItem%, "&First"
        SYS "AppendMenu", third%, 0, ID.Third.SecondItem%, "&Second"
        SYS "AppendMenu", third%, 0, ID.Third.Square%, "S&quare a Number"
 
        SYS "CreateMenu" TO hmenu%
        SYS "AppendMenu", hmenu%, MF_POPUP, first%, "&First"
        SYS "AppendMenu", hmenu%, MF_POPUP, second%, "&Second"
        SYS "AppendMenu", hmenu%, MF_POPUP, third%, "&Third"
        SYS "SetMenu", @hwnd%, hmenu%
        SYS "DrawMenuBar", @hwnd%
        VDU 26
 
        REM Create a dialog box
        SquareDlg% = FN_newdialog("Square a number", 92, 61, 160, 80, 8, 1000)
        PROC_static(SquareDlg%, "Enter a number :", ID.Square.Static1%, \
        \                       8, 8, 64, 16, 0)
        PROC_static(SquareDlg%, "Your number squared is:", ID.Square.Static2%, \
        \                       8, 29, 64, 16, 0)
        PROC_editbox(SquareDlg%, "", ID.Square.InputEditbox%, \
        \                        65, 7, 64, 14, ES_NUMBER)
        PROC_editbox(SquareDlg%, "", ID.Square.OutputEditbox%, \
        \                        65, 30, 64, 14, ES_READONLY)
        PROC_pushbutton(SquareDlg%, "Calculate", ID.Square.CalcButton%, \
        \                           12, 60, 56, 14, BS_DEFPUSHBUTTON)
        PROC_pushbutton(SquareDlg%, "Close", ID.Square.CloseButton%, \
        \                           92, 60, 56, 14, 0)
 
        DIM Click%(2), click%(2)
        ON SYS Click%() = @msg%, @wparam%, @lparam% : RETURN
 
        REPEAT
          click%() = 0
          SWAP Click%(), click%()
 
          CASE click%(1) AND &FFFF OF
 
            WHEN ID.First.FirstItem%:
              SYS "MessageBox", @hwnd%, STR$(ID.First.FirstItem%), "Menu ID", 0
 
            WHEN ID.First.SecondItem%:
              SYS "MessageBox", @hwnd%, STR$(ID.First.SecondItem%), "Menu ID", 0
 
            WHEN ID.First.ThirdItem%:
              SYS "MessageBox", @hwnd%, STR$(ID.First.ThirdItem%), "Menu ID", 0
 
            WHEN ID.Second.FirstItem%:
              SYS "MessageBox", @hwnd%, STR$(ID.Second.FirstItem%), "Menu ID", 0
 
            WHEN ID.Second.SecondItem%:
              SYS "MessageBox", @hwnd%, STR$(ID.Second.SecondItem%), "Menu ID", 0
 
            WHEN ID.Second.ThirdItem%:
              SYS "MessageBox", @hwnd%, STR$(ID.Second.ThirdItem%), "Menu ID", 0
 
            WHEN ID.Third.FirstItem%:
              SYS "MessageBox", @hwnd%, STR$(ID.Third.FirstItem%), "Menu ID", 0
 
            WHEN ID.Third.SecondItem%:
              SYS "MessageBox", @hwnd%, STR$(ID.Third.SecondItem%), "Menu ID", 0
 
            WHEN ID.Third.Square%:
              PROC_showdialog(SquareDlg%)
 
            WHEN ID.Square.CalcButton%
              SYS "GetDlgItemInt", !SquareDlg%, ID.Square.InputEditbox% TO num%
              SYS "SetDlgItemInt", !SquareDlg%, ID.Square.OutputEditbox%, num%^2, 1
 
            WHEN ID.Square.CloseButton%
              PROC_closedialog(SquareDlg%)
 
          ENDCASE
          WAIT 1
        UNTIL FALSE
 
        END
This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
allocating_20item_20ids_20automatically.txt · Last modified: 2024/01/05 00:22 by 127.0.0.1