OnPopupInit - cCJAction

Event is called before any popup menu, popup toolbar or combobox is displayed

Type: Event

Parameters: Variant vCommandBarControl Handle hoCommandBarControls

ParameterDescription
vCommandBarControlPointer to the COM control that was executed. If used, this must be bound to a DataFlex proxy object, which should be based cCJCommandBarControl or one if its sub-classes. This is rarely needed.
hoCommandBarControlsHandle of a DataFlex cCJCommandBarControls object that is bound to the COM object.


Syntax
Procedure OnPopupInit Variant vCommandBarControl Handle hoCommandBarControls

Description

OnPopupInit is called before any popup menu or popup toolbar is displayed. It provides a custom hook where you can make any changes in the popup menu such as adding items, hiding items, disabling items, etc. This is called as part of the private PopupInit process, which will already do much of this work for you.

Two parameters are passed to this event. The vCommandBarControl is a pointer to the COM control that was selected. If you need to use this object you will need to create a DataFlex proxy object based on cCJCommandBarPopup, bind the pointer to this object, use it, and destroy it. It is unlikely that you will ever need to do this.

The hoCommandBarControls parameter is a DataFlex proxy object based on cCJCommandBarControls, which is a collection object that provides access to all child item objects. You are far more likely to use this object. Because it is passed to you, you do not have to worry about destroying it (in fact you should not destroy it).

OnExecute and OnPopupInit

OnExecute is called when your menu or toolbar item is a non-popup item. If your menu or toolbar item is a popup item, the OnPopupInit event is sent instead. An item's type is controlled by the control's peControlType property.

The PopupInit Process

When a popup menu or toolbar item is selected, the private message PopupInit is sent to the cCJCommandBarSystem object. It does the following:

1. It sends Update to all COM child items of this object (actually it sends it to the child action objects). This ensures that each child's enabled, checked and visible state is correct.

2. It calls OnPopupInit.

If the functions IsChecked, IsEnabled and IsVisible are property coded in your child objects you will not need to do anything within OnPopupInit to set these child item properties. If you are not using these functions to set these properties you will need to write code to handle this by setting their pbChecked, pbEnabled and pbVisible properties yourself.

Enabling and Checking Popup Menu Items

If you wish you can set the checked states and enabled states of popup menu items by setting their pbChecked and pbEnabled states. This is a less flexible way to handle this but it will work and, in some cases, provide a migration strategy. The following code shows an example of this:

Object oPopupMenu is a cCJMenuItem
    Set peControlType to xtpControlPopup

    Procedure OnPopupInit Variant vCommandBarControl Handle hoCommandBarControls
        Boolean bReadOnly
        Get pbReadOnly to bReadOnly
        Set pbEnabled of oSaveMe to (not(bReadOnly))
        Set pbChecked of oReadOnly to bReadOnly
    End_Procedure
    
    Object oSaveMe is a cCJMenuItem
        Set psCaption to "Save Me"

        Procedure OnExecute Variant vCommandBarControl
            Send SaveThisThing
        End_Procedure

    End_Object

    Object oReadOnly is a cCJMenuItem
        Set psCaption to "Read Only"

        Procedure OnExecute Variant vCommandBarControl
            Boolean to bReadOnly
            Get pbReadOnly to bReadOnly
            Set pbReadOnly to (not(bReadOnly))
            Set pbChecked to (not(bReadOnly))
        End_Procedure

    End_Object
End_Object

While this works it is restrictive. If you move these menu items to any other popup menu, you will also need to change the OnPopupInit code of the old and new popup menus. If one of these items is moved to a toolbar, you will need to create additional logic to update their states any time pbReadOnly changes.

An alternate approach is to allow the items to do all the work via IsChecked and IsEnabled as follows:

Object oPopupMenu is a cCJMenuItem
    Set peControlType to xtpControlPopup
    
    Object oSaveMe is a cCJMenuItem
        Set psCaption to "Save Me"

        Procedure OnExecute Variant vCommandBarControl
            Send SaveThisThing
        End_Procedure

        Function IsEnabled Returns Boolean
            Boolean bReadOnly
            Get pbReadOnly to bReadOnly
            Function_Return (not(bReadOnly))
        End_Function

    End_Object

    Object oReadOnly is a cCJMenuItem
        Set psCaption to "Read Only"
        Procedure OnExecute Variant vCommandBarControl
            Boolean to bReadOnly
            Get pbReadOnly to bReadOnly
            Set pbReadOnly to (not(bReadOnly))
        End_Procedure

        Function IsChecked Returns Boolean
            Boolean bReadOnly
            Get pbReadOnly to bReadOnly
            Function_Return bReadOnly
        End_Function
        
    End_Object
End_Object

These items can now be moved to any menu location without any other changes. If you place these in a toolbar, you can set the item's pbActiveUpdate property to true and the items will be refreshed automatically. This is the suggested approach.

Creating Dynamic Popup Menus

Dynamic popup menus can be created using the following strategy

1. Create a class for the dynamic menu item. This will be based on cCJMenuItem. Within this class you will need to create an OnExecute method that does whatever you need this class to do. You also might need to create a property, which indicates what should happen when this item is selected.

2. Create an object, or even better a class, that is used for the popup menu. This will contain a handle array property to keep track of the dynamically created child object. Create an OnPopupInit event to handle creating the dynamic items. Within this event you will

2.1. Delete all existing dynamic items by sending Destroy to the objects in your handle array and zeroing the array

2.2. Create a dynamic object based on the class created in step 1.

2.3. Set this object's caption and any other properties needed for it to execute.

2.4. Add this dynamic object to the popup menu by sending the AddDynamicControl message.

2.5. Add this dynamic object handle to your array

2.6. Repeat step 2.2 through 2.5 for each new item.

The following example creates classes to build a MRU list.

// create the dynamic menu item class
Class cMRURecentFilesItem is a cCJMenuItem

    Procedure Construct_Object
        Forward Send Construct_Object
        // full name of the file to be loaded
        Property String psFileName
    End_Procedure

    Procedure OnExecute Variant vCommandBarControl
        String sFile
        Handle hoCommandBars
        Get CommandBarSystemObject to hoCommandBars
        Get psFileName to sFile
        Send LoadFile of hoCommandBars sFile
    End_Procedure
    
End_Class

// create the popup menu class
Class cMRURecentFiles is a cCJMenuItem

    Procedure Construct_Object
        Forward Send Construct_Object
        Set psCaption to "Recent Files"
        // this keeps track of all child items that are dynamically created
        Property Handle[] phoArrayofItems
        Set peControlType to xtpControlPopup
    End_Procedure
    
    // augment to display the latest 9 files. We assume that those file are
    // obtained by sending the message Get MRUFiles to the owner commandbar system
     Procedure OnPopupInit Variant vCommandBarControl Handle hCommandBarControls
        Handle  hoCommandBars hoNewItem
        Integer i iItems
        Handle[] hoArrayOfItems
        String[] sArrayOfFileNames
        Variant vItem
        
        // delete all child items
        Get phoArrayofItems to hoArrayOfItems
        Move (SizeOfArray(hoArrayOfItems)) to iItems
        For i from 0 to (iItems-1)
            Send Destroy of hoArrayOfItems[i]
        Loop
        Move (ResizeArray(hoArrayOfItems,0)) to hoArrayOfItems

        Get CommandBarSystemObject to hoCommandBars 
        Get MRUFiles of hoCommandBars to sArrayOfFileNames
        Move (SizeOfArray(sArrayOfFileNames)) to iItems

        // Add the first 9 items as child items.
        Move ((iItems-1) min 9) to iItems
        For i from 0 to iItems
            // dynamically create the item object based on our MRU item class
            Get Create U_cMRURecentFilesItem to hoNewItem
            // set the caption. Prefix with a number for quick access.
            Set psCaption of hoNewItem to ("&" - String(i+1) * sArrayOfFileNames[i])
            // set the File name. In this case it happens to be the same as caption
            Set psFileName of hoNewItem to sArrayOfFileNames[i]
            // dynamically add the menu as a child of the current popup.
            Get AddDynamicControl of hoNewItem hCommandBarControls to vItem
            // keep track in our array 
            Move hoNewItem to hoArrayOfItems[i]
        Loop
        Set phoArrayofItems to hoArrayOfItems

     End_Procedure
End_Class

This popup menu could now be added to any menu or any toolbar with the following code:

Object oRecentFiles is a cMRURecentFiles
End_Object


OnPopupInit and Combo Controls

OnPopupInit is also sent any time a combo control takes the focus (the combo form is selected or the drop down box is invoked). This event can be used to fill a combo list. See cCJCommandBarComboBox for more information about combos and OnPopupInit.