MDI Frame with MDI Windows - Need to know what menu option was selected on the MDI Window

Hi,

I have a MDI Frame with a toolbar.

Added a lot of browses and forms that are also MDI windows.

When I add Menu options to the MDI Children [edit: at runtime using Create(,Create:Item)]
I need to know what Menu Item was selected on the child.

Currently I have it under Accept Loop at the end using CASE, but when I debug the CHILD window every time I click on the browse [the child of the frame] it runs my code in the accept loop.

Is that the only place to do it or must I move my code? (NOTE: MENU’s are created from a custom queue)

Thank you?

Just to be clear the MDI Child window has a MenuBar ?

You should not need to put the Event handling “at the end using CASE”

Each ITEM will have a USE(?MenuItemLabel1). In the Embeditor you should find an OF ?MenuItemLabel1 to handle Event:Accepted i.e. when the Item is clicked.

Or in the Window Designer you can double click on the Menubar and it will open the Menu Editor. In that the Menu Editor you can click on each Item and there is a Link for Embeds where you can open the Event:Accepted for that Item and add your code.

image

image

Carl,

Yes the MDI Child window has a MenuBar.

But the menu is created at runtime from a MenuQueue, specific for that window and not hard-coded. So they do not have USE labels.

Show your code.

You probably are not filtering Events. I would think you want something like.

IF ACCEPTED() THEN         !Got an Event Accepted
   IF ?{PROP:Type} = Create:ITEM THEN   !And its for a Menu ITEM
      MenuItemQ:FEQ = ?    !FYI ?=FEQ with Event, which = ACCEPTED() in this case
      GET(MenuItemQ, MenuItemQ:FEQ)
      IF ~ERRORCODE() THEN              !Found in my Dynamic Menu Q
         DO Process_MenuItemQ_Routine
      END    
   END
END

Assuming something like this set up Queue.

MenuItemQ   QUEUE,PRE(MenuItemQ)
FEQ            LONG
MyID           STRING(16)
            END 

    MenuItemQ:FEQ  = CREATE(0,Create:ITEM, ?MenuParent)
    MenuItemQ:MyID = 'Blarg'
    ADD(MenuItemQ, MenuItemQ:FEQ)
    MenuItemQ:FEQ{PROP:Text}='Blarg Processing'
    MenuItemQ:FEQ{PROP:Hide}=False

There are other ways like storing an ID in a User Defined property, or HLP prop, or using the Prop:Text to ID the Item like below:

IF ACCEPTED() THEN      !Got an Event Accepted
   IF ?{PROP:Type} = Create:ITEM THEN   !And its for a Menu ITEM
      CASE ?{PROP:Text} 
      OF 'Blarg Processing' ;  DO MenuItem_Blarg_Rtn
      END
   END
END

Carl,

Child Window .init 8001

Window_Optional_Menu_Create('MN-CON-PAYRUN',?ThisWindow_Options_MENU,MenuQueue)

This builds the menu queue for this window

Then “ThisWindow.TakeAccepted PROCEDURE” [5000]

 DO Check_UserMenu_Option_Accepted


Check_UserMenu_Option_Accepted     ROUTINE

        MenuQueue.ExecNumber = ACCEPTED()
        GET(MenuQueue,MenuQueue.ExecNumber)
        IF ERRORCODE()
            Continue# = False
        END

    ! Continue of Menu item selected
    ! ----------------------------------------------------------
        IF Continue# = True 
            CASE CLIP(MenuQueue.ExecString)
            OF 'LOCK'
.............

No problem jumps out at me. But the code is not complete because I don’t see where there is Continue# = True .

Using Implicit variable is a Bad Idea (says that in the help), so remove the use of Continue#. If you need a variable in TakeAccepted then define one in the Data Embed. I’m never quite sure of the Scope and Lifetime of Implicit variables (it did change around C4) but I don’t use them.

I don’t see the need for Continue#. Change the IF ERRORCODE() to EXIT the Routine. The FEQ Accepted was not found in the Queue so there is no need for the code to continue.

I note you didn’t CLEAR(MenuQueue) before the GET so when the GET fails the MenuQueue.ExecString variable has the previous value that could accidentally get used and would probably cause your bug that every Accepted executes it.

Changed code below:

!revised to remove Continue#

 DO Check_UserMenu_Option_Accepted

Check_UserMenu_Option_Accepted     ROUTINE
        CLEAR(MenuQueue)   !<=== change to add Clear() so if Get() fails the Q has no .ExecString
        MenuQueue.ExecNumber = ACCEPTED()
        GET(MenuQueue,MenuQueue.ExecNumber)
            !Insert debug output like  
            IF ACCEPTED(){PROP:Type}=Create:Item THEN 
                 Trace('Check_UserMenu_Option_Accepted ACCEPTED()=' & ACCEPTED() & 'ErrorCode='& ErrorCode() &'  MenuQueue.ExecNumber=' & MenuQueue.ExecNumber etc
            END 
        IF ERRORCODE()
            EXIT    !was Continue# = False  <===== change
        END

    ! Continue of Menu item selected
    ! ----------------------------------------------------------
!n/a ===>   IF Continue# = True    <==== Change - due to EXIT on Error above this is Not Needed
      CASE CLIP(MenuQueue.ExecString)
      OF 'LOCK'
...

There should be No need for CLIP() in CASE CLIP(MenuQueue.ExecString) … unless that variable is a CSTRING or PSTRING and you failed to CLIP on Assignment. If that is a Clarion STRING then it is auto clipped for comparisons like CASE or IF.

1 Like

Carl,

Thanks.

IF ?{PROP:Type} = Create:ITEM THEN

Filtered the accept loop to only returned the selected Menu options and not post when other options were clicked on the screens.

Appreciate the help.

@CarlBarnes , there’s a problem with above code in that we don’t know what TRACE does, and it might change the value in ERRORCODE()

1 Like

you could wrap the Trace call with PUSHERRORS() and POPERRORS()

2 Likes