Announcement

Collapse
No announcement yet.

How Do I change the state of a Menu Item

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • How Do I change the state of a Menu Item

    How do I change the state of the "Insert" menu item in the following code?

    Code:
        MENU NEW BAR TO hMenu
        MENU NEW POPUP TO hPopUp1
        MENU ADD POPUP, hMenu, "File", hPopUp1, %MF_ENABLED
            MENU ADD STRING, hPopUp1, "&Open File" + $TAB + "Ctrl+O", _
                %IDM_EDIT_OPENFILE, %MF_ENABLED
            MENU ADD STRING, hPopUp1, "&Save File" + $TAB + "Ctrl+S", _
                %IDM__SAVEFILE, %MF_GRAYED
        MENU NEW POPUP TO hPopUp1
        MENU ADD POPUP, hMenu, "Edit", hPopUp1, %MF_ENABLED
            MENU ADD STRING, hPopUp1, "Undo", %IDM_EDIT_UNDO, _
                %MF_GRAYED
            MENU ADD STRING, hPopUp1, "Redo", %IDM_EDIT_REDO, _
                %MF_GRAYED
            MENU ADD STRING, hPopUp1, "-", 0, 0
            MENU ADD STRING, hPopUp1, "Search/Replace", %IDM_EDIT_SEARCHREPLACE, _
                %MF_GRAYED
            MENU ADD STRING, hPopUp1, "-", 0, 0
            MENU NEW POPUP TO hPopUp2
            MENU ADD POPUP, hPopUp1, "Insert", hPopUp2, %MF_GRAYED
                MENU ADD STRING, hPopUp2, "RTL Marker", %IDM_EDIT_RTLMARKER, _
                    %MF_ENABLED
                MENU ADD STRING, hPopUp2, "LTR Marker", %IDM_EDIT_LTRMARKER, _
                    %MF_ENABLED
    I have RTFM but none of my permutations work

    Bob

  • #2
    Bob,

    I didn't think that parents can have their check state set - only children which
    result from Menu Add String.

    With Menu Add Popup, the only state Help recognizes are:

    %MF_DISABLED
    Disable the item so that it cannot be selected.
    %MF_ENABLED
    Enable the item so that it can be selected.
    .....

    Whoops! I stand corrected. I tried Menu Set State using position (on one of my own apps), and it works fine. Your code would be something like this:

    Code:
    Menu Set State hPopup2, 10, %MF_CHECKED
    (that's if 10 is the correct position ... I don't know if I counted right in your statements).
    Last edited by Gary Beene; 23 Mar 2009, 09:15 AM.

    Comment


    • #3
      Menu Set State hPopup2, 10, %MF_CHECKED(that's is 10 is the correct position ... I don't know if I counted right in your statements).
      Use the BYCMD flag option in MENU SET STATE statement and you don't have to count. Also the code will work without change if you rearrange or otherwise change the position of an item on the menu.
      Michael Mattias
      Tal Systems (retired)
      Port Washington WI USA
      [email protected]
      http://www.talsystems.com

      Comment


      • #4
        Yep, in general that's the better approach. But a popup menu doesn't have an id. Only items added with Menu Add String get one.

        Comment


        • #5
          But a popup menu doesn't have an id. Only items added with Menu Add String get one.
          Huh?

          If there is a menu item with a check (on or off), that menu item has an ID.

          And while not a DDT guy, I believe you add 'checked' items with MENU ADD STRING and then you set or unset the MF_CHECKED/MF_UNCHECKED states of same.
          Michael Mattias
          Tal Systems (retired)
          Port Washington WI USA
          [email protected]
          http://www.talsystems.com

          Comment


          • #6
            Gary

            Still can't get it right - will keep on trying - I must have a bug somewhere

            Many thanks, Bob
            Last edited by Robert Wallace; 23 Mar 2009, 09:55 AM. Reason: Plrevious text incorrect.

            Comment


            • #7
              Michael,

              The issue is getting the check in the first place.

              The DDT command for adding a popup doesn't allow for assigning an ID.

              Code:
              MENU ADD POPUP, hMenu, txt$, hPopup, state& [, AT [BYCMD] pos&]
              like it does for adding a string

              Code:
              MENU ADD STRING, hMenu, txt$, id&, state& [, AT [BYCMD] pos&] [,  CALL callback]
              So when I add a popup to a menu bar, I can't check it. But when I add a popup to a popup, I can check the second popup because I add it to the first popup using the Menu Add String command.

              Perhaps there's an SDK approach to assigning an ID to a but the DDT commands don't seem to show it.

              I also tried the position approach to add a check to a popup that's attached to the Menu Bar, but a check won't appear. Apparently a popup added to a popup can be checked, but a popup added to the menu bar cannot.

              And finally, surely there's a better terminology that what I've just used. Help sometimes seems slack in using terminology in exactly the same way every time. I found all of these in Help:

              menu bar
              popup menu
              child menu
              popup child menu
              parent menu
              menu
              item
              menu item
              child popup menu
              sub-menu
              popup
              string
              Last edited by Gary Beene; 23 Mar 2009, 10:09 AM.

              Comment


              • #8
                ??
                You don't check a menu item which invokes a popup menu. The checks should go on individual menu items which represent an option.

                i.e.
                Code:
                FILE   EDIT   [COLOR="Red"]OPTIONS[/COLOR]  HELP 
                                   Punt
                                 X Run 
                                    Pass

                ??

                What does it mean when a popup menu is checked? Me, I think it means "user confusion."

                If the popup menu is not applicable to the current condition of the program the menu item which invokes that menu should either be removed or disabled. (I prefer disabled, to show user "yes, this menu can be used, but not right now" and also so all the menu items are in the same place each time that the menu appears).
                Michael Mattias
                Tal Systems (retired)
                Port Washington WI USA
                [email protected]
                http://www.talsystems.com

                Comment


                • #9
                  In the main Dialog I have:

                  Code:
                  gmenu1 = AttachMENU1(hDlg)
                  later on I have :

                  Code:
                    MENU SET STATE gmenu1, BYCMD %IDM_EDIT_SEARCHREPLACE, %MF_ENABLED
                    MENU SET STATE gmenu1, 10, %MF_ENABLED
                  The first line works correctly but I just cannot find out how I correctly code the second line I have tried 10 & 8 but no luck.

                  Baffled

                  Bob

                  Comment


                  • #10
                    Michael,

                    I agree with you - that I would normally not check a parent menu item. I'd check one of it's children.

                    But Bob didn't ask if he should, he only asked how to do it.

                    But now that you speak of it, if I have several children menu items it might actually be ok to check the parent if any one of the children were checked - just as a visual flag to tell me that one of the children is checked. I can't think of a really "great" reason to do it, but it doesn't seem totally unreasonable.

                    Comment


                    • #11
                      Bob,

                      Can you post a complete example of what's not working? I'm having trouble using just the snippets.

                      When I post, I like to give something that can be copy/pasted in the PowerBASIC IDE - makes it easier for someone to test a fix for me. I also try to take out any code that doesn't apply to the problem - less is better, but enough to see it in action.
                      Last edited by Gary Beene; 23 Mar 2009, 10:32 AM.

                      Comment


                      • #12
                        Code:
                        MENU SET STATE gmenu1, BYCMD %IDM_EDIT_SEARCHREPLACE, %MF_ENABLED
                        MENU SET STATE gmenu1, 10, %MF_ENABLED
                        The first line works correctly but I just cannot find out how I correctly code the second line I have tried 10 & 8 but no luck
                        If the second is the same menu item as the first you should be able to use...
                        Code:
                         
                        MENU SET STATE gmenu1, BYCMD %IDM_EDIT_SEARCHREPLACE, %MF_GRAYED
                        ???

                        Wait a minute... you want to do this by index?

                        With SDK style...

                        All menu items occupy one position be it a regular command (string) item, a popup menu or a separator. Positions are indexed starting with item zero.

                        I would "assume" DDT indexes all items as well, although DDT might set the first item's index to "one" instead of "zero", since DDT does everything else "one-based"
                        Last edited by Michael Mattias; 23 Mar 2009, 10:37 AM.
                        Michael Mattias
                        Tal Systems (retired)
                        Port Washington WI USA
                        [email protected]
                        http://www.talsystems.com

                        Comment


                        • #13
                          I posted some sample code a long time ago that showed how to do a lot of things with menus - setting control ids, states, etc. Maybe it will offer some ideas: Owner Drawn Menu Bar
                          Bernard Ertl
                          InterPlan Systems

                          Comment


                          • #14
                            From the Help File:

                            Syntax
                            MENU SET STATE hMenu, [BYCMD] pos&, state&

                            Remarks
                            Change the state of the menu item identified by pos&.

                            hMenu
                            Double-word or Long-integer variable containing the handle of the menu that contains the item to change

                            pos&
                            Position within the menu, of the menu item to be changed. If the BYCMD option is specified, pos& refers to the unique menu item identifier of the item. Otherwise, pos& indicates the physical position of the menu item within the menu, where pos& = 1 for the first position, pos& = 2 for the second position, and so on.
                            .

                            The above gives the impression that "[BYCMD] pos&" and "pos&" are interchangeable on the same handle but this does not seem to be the case.

                            It would appear from Bern's sample software that I need an API call to get to the sub-levels and as this is not documented in the HELP file I will now give up trying to do what I wanted.

                            I just don't like doing something that is unclear (to me) in the Documentation because this is the quickest way of writing unuseable software.

                            Bob

                            PS Sounds defeatest but I have spent two days trying to change the state of ONE Menu item + the time others have spent trying to help me.

                            Comment


                            • #15
                              Before giving up, would you post compilable code that shows just when and where such changes are to be put into effect( preferably extracted from the program you're working on).
                              Rod
                              In some future era, dark matter and dark energy will only be found in Astronomy's Dark Ages.

                              Comment


                              • #16
                                All things considered, that documentation is not bad at all.

                                Accrording to that doc you should be able to set the state of any item using EITHER the command id or the ordinal position of the item, and should be able to do it without making only DDT calls (no WinAPI *Menu* calls).

                                Gin up a compilable little demo program and post here. Someone will find whatever is wrong.

                                MCM
                                Michael Mattias
                                Tal Systems (retired)
                                Port Washington WI USA
                                [email protected]
                                http://www.talsystems.com

                                Comment


                                • #17
                                  Working Code below - The problem is that I can change the state of the main headings using a position but I don't seem to be able to change sub items this way , only by using "BYCMD"

                                  I seem to have an error with "DIALOG REDRAW CBHNDL" so after selecting a test entry you have to pass the cursor over the menu entries to see them change.

                                  Code:
                                  #COMPILE EXE
                                  #DIM ALL
                                  
                                  '------------------------------------------------------------------------------
                                  '   ** Includes **
                                  '------------------------------------------------------------------------------
                                  #PBFORMS BEGIN INCLUDES
                                  
                                  #INCLUDE ONCE "WIN32API.INC"
                                  
                                  #INCLUDE "PBForms.INC"
                                  #PBFORMS END INCLUDES
                                  
                                  GLOBAL gmenu1 AS DWORD
                                  
                                  %IDM_NEW_ALLOWCHANGES   = 1067
                                  %IDM_CLEARMARKERS       = 1068
                                  %IDM_EDIT_OPENFILE      = 1074
                                  %IDM__SAVEFILE          = 1075
                                  %IDM_EXIT               = 1076
                                  %IDM_HELP_ABOUT         = 1077
                                  %IDM_EDIT_SEARCHREPLACE = 1078
                                  %IDC_PROGBAR1           = 1079
                                  %IDM_EDIT_UNDO          = 1080
                                  %IDM_EDIT_REDO          = 1081
                                  %IDM_EDIT_RTL           = 1084
                                  %IDM_EDIT_LTR           = 1085
                                  %IDM_MAINHEADINGS       = 1086
                                  %IDM_SUBHEADINGS        = 1087
                                  %IDM_SUBITEMS           = 1088
                                  
                                  FUNCTION PBMAIN () AS LONG
                                    REGISTER i AS LONG
                                  
                                    ShowDIALOG1 %HWND_DESKTOP
                                  
                                  END FUNCTION
                                  
                                  CALLBACK FUNCTION ShowDIALOG1Proc()
                                    STATIC DDTEndFlag AS LONG
                                     SELECT CASE AS LONG CBMSG
                                          CASE %WM_NCACTIVATE
                                              STATIC hWndSaveFocus AS DWORD
                                              IF ISFALSE CBWPARAM THEN
                                                  ' Save control focus
                                                  hWndSaveFocus = GetFocus()
                                              ELSEIF hWndSaveFocus THEN
                                                  ' Restore control focus
                                                  SetFocus(hWndSaveFocus)
                                                  hWndSaveFocus = 0
                                              END IF
                                              
                                          CASE %WM_COMMAND
                                              ' Process control notifications
                                              SELECT CASE AS LONG CBCTL
                                                  CASE %IDM_MAINHEADINGS
                                                     IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                                        MENU SET STATE GMenu1, 1, %MF_ENABLED
                                                        MENU SET STATE GMenu1, 2, %MF_ENABLED
                                                        MENU SET STATE GMenu1, 3, %MF_ENABLED
                                                     END IF
                                                     DIALOG REDRAW CBHNDL
                                                  CASE %IDM_SUBHEADINGS
                                                     IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                                        MENU SET STATE GMenu1, 5, %MF_ENABLED        '<<<<<<<<<<<<<<<What value do I put here to enable subentries
                                                     END IF
                                                     DIALOG REDRAW CBHNDL
                                                  CASE %IDM_SUBITEMS
                                                     IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                                       MENU SET STATE GMenu1, BYCMD %IDM_EDIT_OPENFILE, %MF_ENABLED
                                                       MENU SET STATE GMenu1, BYCMD %IDM__SAVEFILE, %MF_ENABLED
                                                       MENU SET STATE GMenu1, BYCMD %IDM_EXIT, %MF_ENABLED
                                                       MENU SET STATE GMenu1, BYCMD %IDM_EDIT_UNDO, %MF_ENABLED
                                                       MENU SET STATE GMenu1, BYCMD %IDM_EDIT_REDO, %MF_ENABLED
                                                       MENU SET STATE GMenu1, BYCMD %IDM_EDIT_LTR, %MF_ENABLED
                                                       MENU SET STATE GMenu1, BYCMD %IDM_EDIT_RTL, %MF_ENABLED
                                                       MENU SET STATE GMenu1, BYCMD %IDM_EDIT_SEARCHREPLACE, %MF_ENABLED
                                                       
                                                     END IF
                                                     DIALOG REDRAW CBHNDL
                                              END SELECT
                                          CASE %WM_CLOSE
                                              IF DDTEndFlag = 0 THEN
                                                         DDTEndFlag=1
                                                         DIALOG END CBHNDL
                                                         ' DDT seems to send the %WM_CLOSE and %WM_DESTROY
                                                         ' messages so the flag is necessary to prevent an
                                                         ' infinite loop.
                                              END IF
                                              FUNCTION=0
                                              EXIT FUNCTION
                                  
                                          CASE %WM_SYSCOMMAND
                                             IF (CBWPARAM AND &HFFF0)= %SC_CLOSE THEN
                                                SendMessage CBHNDL, %WM_CLOSE,0,0
                                               FUNCTION = 1
                                               EXIT FUNCTION
                                             END IF
                                      END SELECT
                                  END FUNCTION
                                  
                                  FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                                  700:
                                      LOCAL lRslt  AS LONG
                                      LOCAL i AS LONG
                                  
                                  #PBFORMS BEGIN DIALOG %IDD_DIALOG1->%IDR_MENU1->%IDR_ACCELERATOR1
                                      LOCAL hDlg   AS DWORD
                                      LOCAL hFont1 AS DWORD
                                      LOCAL hFont2 AS DWORD
                                      LOCAL hFont3 AS DWORD
                                      LOCAL hFont4 AS DWORD
                                      LOCAL hFont5 AS DWORD
                                      LOCAL hFont6 AS DWORD
                                  
                                      DIALOG NEW hParent, "GlobalUTF8Editor", 37, 98, 200, 100, %WS_POPUP OR _
                                          %WS_BORDER OR %WS_DLGFRAME OR %WS_SYSMENU OR %WS_MINIMIZEBOX OR _
                                          %WS_MAXIMIZEBOX OR %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME _
                                          OR %DS_3DLOOK OR %DS_NOFAILCREATE OR %DS_SETFONT, %WS_EX_WINDOWEDGE _
                                          OR %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
                                          %WS_EX_RIGHTSCROLLBAR OR %WS_EX_ACCEPTFILES, TO hDlg
                                  
                                      hFont1 = PBFormsMakeFont("MS Sans Serif", 8, 700, %FALSE, %FALSE, %FALSE, _
                                          %ANSI_CHARSET)
                                          
                                      DIALOG  SEND hDlg, %WM_SETFONT, hFont1, 0
                                      gmenu1 = AttachMENU1(hDlg)
                                  
                                  #PBFORMS END DIALOG
                                  
                                      DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
                                  #PBFORMS BEGIN CLEANUP %IDD_DIALOG1
                                      DeleteObject hFont1
                                  #PBFORMS END CLEANUP
                                  
                                      FUNCTION = lRslt
                                  END FUNCTION
                                      
                                  FUNCTION AttachMENU1(BYVAL hDlg AS DWORD) AS DWORD
                                  #PBFORMS BEGIN MENU %IDR_MENU1->%IDD_DIALOG1
                                      LOCAL hMenu   AS DWORD
                                      LOCAL hPopUp1 AS DWORD
                                      LOCAL hPopUp2 AS DWORD
                                  
                                      MENU NEW BAR TO hMenu
                                      MENU NEW POPUP TO hPopUp1
                                      MENU ADD POPUP, hMenu, "File", hPopUp1, %MF_GRAYED
                                          MENU ADD STRING, hPopUp1, "&Open File" + $TAB + "Ctrl+O", _
                                              %IDM_EDIT_OPENFILE, %MF_GRAYED
                                          MENU ADD STRING, hPopUp1, "&Save File" + $TAB + "Ctrl+S", _
                                              %IDM__SAVEFILE, %MF_GRAYED
                                      MENU NEW POPUP TO hPopUp1
                                      MENU ADD POPUP, hMenu, "Edit", hPopUp1, %MF_GRAYED
                                          MENU ADD STRING, hPopUp1, "Undo", %IDM_EDIT_UNDO, _
                                              %MF_GRAYED
                                          MENU ADD STRING, hPopUp1, "Redo", %IDM_EDIT_REDO, _
                                              %MF_GRAYED
                                          MENU ADD STRING, hPopUp1, "-", 0, 0
                                          MENU ADD STRING, hPopUp1, "Search/Replace", %IDM_EDIT_SEARCHREPLACE, _
                                              %MF_GRAYED
                                          MENU ADD STRING, hPopUp1, "-", 0, 0
                                          MENU NEW POPUP TO hPopUp2
                                          MENU ADD POPUP, hPopUp1, "Insert", hPopUp2, %MF_GRAYED
                                              MENU ADD STRING, hPopUp2, "RTL Marker", %IDM_EDIT_RTL, _
                                                  %MF_GRAYED
                                              MENU ADD STRING, hPopUp2, "LTR Marker", %IDM_EDIT_LTR, _
                                                  %MF_ENABLED
                                      MENU NEW POPUP TO hPopUp1
                                      MENU ADD POPUP, hMenu, "NEW Marker", hPopUp1, %MF_GRAYED
                                          MENU ADD STRING, hPopUp1, "Allow Markers", %IDM_NEW_ALLOWCHANGES, _
                                              %MF_GRAYED
                                          MENU ADD STRING, hPopUp1, "-", 0, 0
                                          MENU ADD STRING, hPopUp1, "Clear Markers", %IDM_CLEARMARKERS, _
                                              %MF_GRAYED
                                      MENU NEW POPUP TO hPopUp1
                                      MENU ADD POPUP, hMenu, "Testing", hPopUp1, %MF_ENABLED
                                          MENU ADD STRING, hPopUp1, "Enable Main Headings", %IDM_MAINHEADINGS, _
                                              %MF_ENABLED
                                          MENU ADD STRING, hPopUp1, "Enable Sub Headings", %IDM_SUBHEADINGS, _
                                              %MF_ENABLED
                                          MENU ADD STRING, hPopUp1, "Enable Sub Items", %IDM_SUBITEMS, _
                                              %MF_ENABLED
                                              
                                      MENU ATTACH hMenu, hDlg
                                  #PBFORMS END MENU
                                      FUNCTION = hMenu
                                  END FUNCTION
                                  '------------------------------------------------------------------------------

                                  Comment


                                  • #18
                                    First, replace the DIALOG REDRAW CBHNDL with MENU DRAW BAR CBHNDL.

                                    Secondly, you will need the handle to the popup in which you want to change the "subheadings" as you call them, or Child Popup Menus.

                                    GMenu1 is pointing to the Top Level Menu, that contains 4 PopUp menus in the program, the API (And by convention the command MENU SET STATE hMenu, [BYCMD] pos&, state&) can find menu items in the entire menu without a problem, whether it's a command deeply nested in the menu structure or not. To change something by position, you need the handle to the popup in which the element that you want to change exists, hence your code under %IDM_MAINHEADINGS works, but that's it, the total number of elements seen by position is 4, you could say there's no positions available beyond that to be affected by position from that point.

                                    To change the state of an element in the menu which is NOT a command, that is, it's a "child" menu, you need the handle to the "parent" menu, and your GMenu1 is not the parent of your "Insert" menu, it belongs to the "Edit" popup. You would need to get the handle to that menu, (not done via DDT code, would need to use API), and then you can enable the menu with either DDT or API.
                                    Code:
                                      LOCAL cMenu AS DWORD
                                      cMenu = GetSubMenu(GMenu1, 1)
                                      MENU SET STATE cMenu, 6, %MF_ENABLED
                                    Note that separators count, and the API counts menu elements from 0, not 1 like DDT does.
                                    Furcadia, an interesting online MMORPG in which you can create and program your own content.

                                    Comment


                                    • #19
                                      Colin

                                      Many thanks for clarifying the problem - the answer is what I suspected from examining Bern's code sample.

                                      The documentation is legally precise but for a non-API user who relies on PBForms the documentation is sadly lacking.

                                      Many thanks to all who tried to help.

                                      Bob

                                      Comment


                                      • #20
                                        Problem Solved !!

                                        After some discussion with Support - the problem was found to be in the code Generated by PBForms. "PBForms re-uses the variables because it is trying to keep code and stack size to a minimum"

                                        To change the state of a Menu Item that does not have a unique menu item identifier it is necessary to change its duplicated variable name to a uniquely named variable. The MENU SET STATE command will then work as described.

                                        R&D has been asked to look into the possibility removing duplicates.

                                        Bob

                                        Comment

                                        Working...
                                        X