Release 10.1A: OpenEdge Development:
Programming Interfaces

> ## Handling ActiveX control events

> Unlike Progress widget events, ActiveX control events often pass parameters. Also, while there are a few standard events common to most ActiveX controls, there are an infinite variety of possible events that are unique to each ActiveX control. Because Progress cannot have direct knowledge of all these possible events and must be able to handle the parameters of many of them, the standard Progress trigger mechanism cannot handle them.

> Instead, Progress allows you to handle ActiveX control events using OCX event procedures. An OCX event procedure is a standard Progress internal procedure that serves as an event handler for ActiveX controls. The parameter-passing mechanism provided for Progress procedures handles most parameters that ActiveX control events typically pass. Progress identifies an OCX event procedure from the way its name is put together. This is the only syntactic feature that distinguishes the Progress internal procedure as an OCX event procedure.

> ##### Creating event procedures in the AppBuilder

> In the AppBuilder, you define OCX event procedures as OCX event triggers. You can identify each ActiveX control event in the AppBuilder event list by the “OCX.” prefix attached to the event name. When you select an event name to define an OCX event trigger, the AppBuilder automatically generates an internal procedure block for the event procedure, including any procedure parameter definitions. (For more information, see OpenEdge Development: AppBuilder .)

> ##### Coding event procedures

> When you create an OCX event trigger in the AppBuilder, the AppBuilder defines an internal procedure template with the following components:

> - A procedure name that identifies the ActiveX control and event being handled.

> - Any required procedure parameter definitions with default mode and data type mappings.

> If you code OCX event procedures in external procedure files other than the one where you instantiate the ActiveX control, you must code the complete event procedure yourself. In addition, you must also add the procedure to the list that Progress searches to find event procedures to handle events. For more information, see the "Managing external procedure files" section.

> ##### Coding event procedure names

> Progress supports two types of OCX event procedures, distinguished by the procedure name:

> - Control-bound event procedures that handle a specific event for a specific control instance.

> - Generic event procedures that handle a specific event for all ActiveX controls in the application.

> Note: Names of event procedures are not case sensitive.

> The names for control-bound event procedures contain three parts, delimited by a period (.). Each part can be quoted if it contains embedded spaces:

> 1. The name of the control-frame (the `NAME` attribute value of the control-frame widget).

> 2. The name of the ActiveX control (the Name property value set in the Property Editor).

> 3. The name of the event that is handled by the procedure.

> As with all internal procedures that you add in the AppBuilder, the `PROCEDURE` statement and procedure name is not visible in the Section Editor. However, this is one that you or the AppBuilder might code:

>     PROCEDURE CtrlFrame.CSSpin.SpinUp .

> This begins the definition for a procedure to handle the SpinUp event for the control named CSSpin in the control-frame named CtrlFrame.

> The names for generic event procedures contain two parts, delimited by a period (.):

> 1. `ANYWHERE`.

> 2. The name of the event that is handled by the procedure.

> The AppBuilder does not provide a mechanism to generate generic event procedures. You must code these yourself in the AppBuilder using the New Procedure dialog box, or you can add them to an external procedure file. Here is an example:

>     PROCEDURE ANYWHERE.SpinUp .

> A generic event procedure with this name handles the SpinUp event for any control instance that does not have a control-bound event procedure defined for the SpinUp event.

> ##### Coding event parameter definitions

> As for any procedure definition, you code event procedure parameters using the `DEFINE` `PARAMETER` statement. When you create an event procedure as an OCX trigger in the AppBuilder, the AppBuilder provides default definitions for all required parameters. These default definitions attempt to specify a Progress data type that is compatible with the COM data type of the corresponding OCX event parameter. This data type generally follows the data type mappings shown in Table 16–4.

> Table 16–4: Data type mappings for OCX event parameters
> COM data type | Progress data type
> --- | ---
> Array | Progress array variable
> Array of bytes |
>     RAW
> Boolean |
>     LOGICAL
> Byte |
>     INTEGER
> Currency |
>     DECIMAL
> Date Double | DATE DATETIME DATETIME-TZ
> Double |
>     DECIMAL
> Integer (2-byte integer) |
>     INTEGER
> Long (4-byte integer) |
>     INTEGER
> Object (COM) |
>     COM-HANDLE
> Single (float) |
>     DECIMAL
> String |
>     CHARACTER
>     LONGCHAR
> Unsigned byte |
>     INTEGER
> Unsigned long (4-byte integer) |
>     INTEGER
> Unsigned short (2-byte integer) |
>     INTEGER
> Variant |
>     ANYTYPE1
> `VT-ARRAY` (if single-dimensional array of bytes) |
>     RAW

> 1You must replace `ANYTYPE`, provided by the AppBuilder in some OCX event trigger templates, with a valid Progress data type.

> For event procedures you write yourself, you can also find the suggested Progress data type for each parameter displayed in the OpenEdge COM Object Viewer for each selected control event. For more information on this viewer, see Chapter 14, " Using COM Objects in the 4GL."

> In the AppBuilder, Progress uses data type mappings from the COM data type specified in the Type Library for the ActiveX control. If Progress cannot determine a data type mapping, the AppBuilder specifies `ANYTYPE` as a place holder. You must change `ANYTYPE` to the data type that most closely matches the expected value. Progress does its best to convert the COM data type to the Progress data type you specify. For more information on a COM data type, see the available documentation on the Microsoft Component Object Model and the event parameter you want to convert, then see Appendix A "COM Object Data Type Mapping." For information on Type Libraries and Progress, see Chapter 14, " Using COM Objects in the 4GL."

> The AppBuilder also provides a default mode option (`INPUT`, `OUTPUT`, or `INPUT-OUTPUT`) for each parameter definition. Here, although Progress does its best to interpret the information in the Type Library for the ActiveX control, this is not a direct mapping. You might have to modify the mode option. If the option chosen by Progress is incorrect, this generates a run-time error. If the event parameter is passed as read-only, define it as an `INPUT` parameter. If you can change its initial value and must pass it back to the ActiveX control, define it as an `INPUT-OUTPUT` parameter. If only the value you return to the ActiveX control has any meaning, define it as an `OUTPUT` parameter.

> Caution: If an `INPUT` parameter passes in a `COM-HANDLE` value, use the `RELEASE` `OBJECT` statement to release the specified COM object when you no longer need it (usually before the event procedure returns). Otherwise, the component handle might become unavailable and the COM object might never be released. Also, not releasing the COM object in the event procedure can cause unpredictable behavior with some controls.

> Caution: If an event procedure has any `INPUT-OUTPUT` or `OUTPUT` parameters and contains any I/O-blocking statements, such as `SET` or `UPDATE`, the output parameters are not returned to the control.

> ##### Using system handles in OCX event procedures

> Progress allows you to obtain the identities of both the ActiveX control that generates an event and the associated control-frame widget from within an OCX event procedure. The `COM-SELF` system handle returns the component handle of the ActiveX control and the `SELF` system handle returns the widget handle of the control-frame. This is especially useful in generic event procedures where the source of an event cannot be known.

> Unlike for 4GL ON triggers, the `RETURN` `NO-APPLY` statement has no affect in an OCX event procedure. Some COM object events provide a similar mechanism using output parameters. For example, the standard KeyPress event passes a key code as an `INPUT-OUTPUT` parameter. If you set this parameter to 0 in the event handler, the key is discarded.

> Note: To trigger a Progress widget event from the 4GL, you use the `APPLY` statement. However, to trigger an ActiveX control event in the 4GL, you execute its OCX event procedure as a standard internal procedure, passing any required parameters.

> ##### Event handler example

> The following example shows an OCX event trigger for the `NewItem` event of the `CSComboBox` control `MyCombo` in control-frame `CtrlFrame-2`. This event occurs when a user enters an item in the text box that is not in the combo box list:

>     PROCEDURE CtrlFrame-2.MyCombo.NewItem .

>     DEFINE INPUT-OUTPUT PARAMETER i-ComboText AS CHARACTER NO-UNDO.
>     DEFINE INPUT-OUTPUT PARAMETER i-KeepFocus AS INTEGER NO-UNDO.

>         COM-SELF:AddItem(i-ComboText, 1).
>         i-KeepFocus = -1.

>     END PROCEDURE.

> The programmer uses the `COM-SELF` handle to add the new text item to the list with the `AddItem()` method. Setting `i-KeepFocus` to -1 ensures that the control maintains input focus after the item is added to the list.

> If this event procedure is in the AppBuilder-generated application file, the programmer might otherwise choose to call the `AddItem()` method indirectly using the component handles provided by the AppBuilder (`chCtrlFrame-2`) and the control-frame COM object (`MyCombo` property):

>     PROCEDURE CtrlFrame-2.MyCombo.NewItem .

>     DEFINE INPUT-OUTPUT PARAMETER i-ComboText AS CHARACTER NO-UNDO.
>     DEFINE INPUT-OUTPUT PARAMETER i-KeepFocus AS INTEGER NO-UNDO.

>         chCtrlFrame-2:MyCombo:AddItem(i-ComboText, 1).
>         i-KeepFocus = -1.

>     END PROCEDURE.

Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095