ActiveX controls are third-party custom controls that you can integrate in a Natural dialog.
This document covers the following topics:
ActiveX controls and Natural use different terminology in two cases:
ActiveX Control | Natural |
---|---|
Property | Attribute |
Method | PROCESS GUI Statement Action
|
The handle of an ActiveX control is defined similar as a built-in dialog element, but its individual aspects are coded in double angle brackets.
Example:
01 #OCX-1 HANDLE OF <<OCX-Table.TableCtrl.1 [Table Control]>>
In the above example, Table.TableCtrl.1
is the program
ID (ProgID) under which the ActiveX control is registered in the system
registry. The prefix OCX-
identifies the control as an ActiveX
control. [Table Control]
is an optional part of the definition and
provides a readable name.
You create an instance of an ActiveX control by using the
PROCESS GUI
statement action
ADD
. To do so, the value of the
TYPE
attribute must be
the ActiveX control's ProgID prefixed with the string OCX-
and put
in double angle brackets. The ProgID is the name under which the control is
registered in the system registry. You can additionally provide a readable name
in square brackets. In addition to that, you can set Natural attributes such as
RECTANGLE-X
as well as
the ActiveX control's properties. The property name must be preceded by the
string PROPERTY-
and this combination must be put in double angle
brackets. Furthermore, you can suppress the ActiveX control's events. To do
this, the event name must be preceded by the string SUPPRESS-EVENT
this combination must be delimited by double angle brackets. The value of the
SUPPRESS-EVENT
property is either the Natural
keyword SUPPRESSED
or NOT-SUPPRESSED
.
Example:
PROCESS GUI ACTION ADD WITH PARAMETERS HANDLE-VARIABLE = #OCX-1 TYPE = <<OCX-Table.TableCtrl.1 [Table Control]>> PARENT = #DLG$WINDOW RECTANGLE-X = 44 RECTANGLE-Y = 31 RECTANGLE-W = 103 RECTANGLE-H = 46 <<PROPERTY-HeaderColor>> = H'FF0080' <<PROPERTY-Rows>> = 16 <<PROPERTY-Columns>> = 4 <<SUPPRESS-EVENT-RowMoved>> = SUPPRESSED <<SUPPRESS-EVENT-ColMoved>> = SUPPRESSED END-PARAMETERS
Simple properties are properties that do not have parameters. Simple
properties of an ActiveX control are addressed like attributes of built-in
controls. The attribute name is built by prefixing the property name with
PROPERTY-
and enclosing it in angle brackets. The properties of an
ActiveX control are displayed in the
Component Browser. The
following examples assume that the ActiveX control #OCX-1
has the
simple properties CurrentRow
and
CurrentCol
.
Example:
* Get the value of a property. #MYROW := #OCX-1.<<PROPERTY-CurrentRow>> * Put the value of a property. #OCX-1.<<PROPERTY-CurrentCol>> := 17
The data types of ActiveX control properties are those defined by OLE Automation. In Natural, each of these data types is mapped to a corresponding Natural data type. The following table shows which OLE Automation data type is mapped to which Natural data type.
Read the table in the following way: Assume an ActiveX control
#OCX-1
has a property named "Size",
which is of type VT_R8. Then the expression
#OCX-1.<<PROPERTY-SIZE>>
has the type F8 in
Natural.
Note:
The Component
Browser displays the corresponding Natural data types
directly.
Some special data types are considered individually in the following:
A property of type Color appears in Natural as a B3 value. The B3 value is interpreted as an RGB color value. The three bytes contain the red, green and blue elements of the color, respectively. Thus for example H'FF0000' corresponds to red, H'00FF00' corresponds to green, H'0000FF' corresponds to blue and so on.
Example:
... 01 #COLOR-RED (B3) ... #COLOR-RED := H'FF0000' #OCX-1.<<PROPERTY-BackColor>> := #COLOR-RED ...
A property of type Picture appears in Natural as HANDLE OF
OBJECT
. Alternatively you can assign an Alpha value to a Picture
property. The Alpha value must then contain the file name of a Bitmap
(.bmp) file.
Example (usage of Picture properties):
... 01 #MYPICTURE HANDLE OF OBJECT ... * Assign a Bitmap file name to a Picture property. #OCX-1.<<PROPERTY-Picture>>:= '11100102.bmp' * * Get it back as an object handle. #MYPICTURE := #OCX-1.<<PROPERTY-Picture>> * * Assign the object handle to a Picture property of another control. #OCX-2.<<PROPERTY-Picture>>:= #MYPICTURE ...
A property of type Font appears in Natural as HANDLE OF
OBJECT
. You can alternatively assign a HANDLE OF FONT
to a
Font property. Additionally you can assign an Alpha value to a Font property.
The Alpha value must then contain a font specification in the form that is
returned by the STRING
attribute of a
HANDLE OF FONT
.
Example 1 (using HANDLE OF OBJECT
):
... 01 #MYFONT HANDLE OF OBJECT ... * Create a Font object. CREATE OBJECT #MYFONT OF CLASS 'StdFont' #MYFONT.Name := 'Wingdings' #MYFONT.Size := 20 #MYFONT.Bold := TRUE * * Assign the Font object as value to a Font property. #OCX-1.<<PROPERTY-TitleFont>> := #MYFONT ...
Example 2 (using HANDLE OF FONT
):
... 01 #FONT-TAHOMA-BOLD-2 HANDLE OF FONT ... * Create a Font handle. PROCESS GUI ACTION ADD WITH PARAMETERS HANDLE-VARIABLE = #FONT-TAHOMA-BOLD-2 TYPE = FONT PARENT = #DLG$WINDOW STRING = '/Tahoma/Bold/0 x -27/ANSI VARIABLE SWISS DRAFT/W/2/3/' END-PARAMETERS GIVING *ERROR ... * Assign the Font handle as value to a Font property. #OCX-1.<<PROPERTY-TitleFont>> := #FONT-TAHOMA-BOLD-2 ...
Example 3 (using a font specification string):
... 01 #FONT-TAHOMA-BOLD-2 HANDLE OF FONT ... * Create a Font handle. PROCESS GUI ACTION ADD WITH PARAMETERS HANDLE-VARIABLE = #FONT-TAHOMA-BOLD-2 TYPE = FONT PARENT = #DLG$WINDOW STRING = '/Tahoma/Bold/0 x -27/ANSI VARIABLE SWISS DRAFT/W/2/3/' END-PARAMETERS GIVING *ERROR ... * Assign the font specification as value to a Font property. #OCX-1.<<PROPERTY-TitleFont>> := #FONT-TAHOMA-BOLD-2.STRING ...
A property of type Variant is compatible with any Natural data type.
This means that the type of the expression
#OCX-1.<<PROPERTY-Value>>
is not checked by the
compiler, if "Value" is a property of type Variant.
So the assignments #OCX-1.<<PROPERTY-Value >> :=
#MYVAL
and #MYVAL := #OCX-1.<<PROPERTY-Value >>
are allowed independently of the type of the variable
#MYVAL
. It is however up to the ActiveX control to
accept or reject a particular property value at runtime, or to deliver the
value in the requested format. If it does not, the ActiveX control will usually
raise an exception. This exception is returned as a Natural error code to the
Natural program. Here it can be handled in the usual way in an ON
ERROR
block. You should check the documentation of the ActiveX control
to find out which data formats are actually allowed for a particular property
of type Variant.
An expression like
#OCX-1.<<PROPERTY-Value>>
(where
"Value" is a Variant property) can occur as source
operand in any statement. However, it can be used as target operand only in
assignment statements.
Examples (usage of Variant properties):
(Assume that "Value" is a property of
type Variant of the ActiveX control #OCX-1
)
... 01 #STR1 (A100) 01 #STR2 (A100) ... * These statements are allowed, because the Variant property is used * as source operand (its value is read). #STR1 := #OCX-1.<<PROPERTY-Value>> COMPRESS #OCX-1.<<PROPERTY-Value>> 'XYZ' to #STR2 ... * This leads to an error at compile time, because the Variant * property is used as target operand (its value is modified) in * a statement other than an assignment. COMPRESS #STR1 "XYZ" to #OCX-1.<<PROPERTY-Value>> ... * This statement is allowed, because the Variant property is used * as target operand in an assignment. COMPRESS #STR1 'XYZ' to #STR2 #OCX-1.<<PROPERTY-Value>> := #STR2 ...
A property of type SAFEARRAY of up to three dimensions appears in a Natural program as an array with the same dimension count, occurrence count per dimension and the corresponding format. (Properties of type SAFEARRAY with more than three dimensions cannot be used in Natural programs.) The dimension and occurrence count of an array property is not determined at compiletime but only at runtime. This is because this information is variable and is not defined at compiletime. The format however is checked at compiletime.
Array properties are always accessed as a whole. So no index notation is necessary and allowed with an array property.
Examples (usage of Array properties):
(Assume that "Values" is a property of
the ActiveX control #OCX-1
an has the type SAFEARRAY of VT_I4)
... 01 #VAL-L (L/1:10) 01 #VAL-I (I4/1:10) ... * This statement is allowed, because the format of the property * is data transfer compatible with the format of the receiving array. * However, if it turns out at runtime that the dimension count or * occurrence count per dimension do not match, a runtime error will * occur. VAL-I(*) := #OCX-1.<<PROPERTY-Values>> ... * This statement leads to an error at compiletime, because * the format of the property is not data transfer compatible with * the format of the receiving array. VAL-L(*) := #OCX-1.<<PROPERTY-Values>> ...
The methods of ActiveX controls are called as actions in a
PROCESS GUI
statement. The same is the case with the complex properties of ActiveX controls
(i. e. properties that have parameters). The methods and properties of an
ActiveX control are displayed in the
Component Browser.
This section covers the following topics:
To perform a method of an ActiveX control the
PROCESS GUI
statement is used. The name of the corresponding PROCESS GUI
action is built by prefixing the method name with METHOD-
and
enclosing it in angle brackets. The ActiveX control handle and the method
parameters (if any) are passed in the WITH
clause of the
PROCESS GUI
statement. The return value of the method (if any) is received in the variable
specified in the USING
clause of the
PROCESS GUI
statement.
This means: To perform a method, you enter a statement
PROCESS GUI ACTION
<<METHOD- methodname>> WITH handlename
[parameter]...
|
[USING
method-return-operand]..
|
Examples:
* Performing a method without parameters: PROCESS GUI ACTION <<METHOD-AboutBox>> WITH #OCX-1 * Performing a method with parameters: PROCESS GUI ACTION <<METHOD-CreateItem>> WITH #OCX-1 #ROW #COL #TEXT * Performing a method with parameters and a return value: PROCESS GUI ACTION <<METHOD-RemoveItem>> WITH #OCX-1 #ROW #COL USING #RETURN
Formats and length of the method parameters and the return value are checked at compiletime against the definition of the method, as it is displayed in the Component Browser.
To get the value of a property that has parameters, the name of
the corresponding PROCESS GUI
action is built by prefixing the
property name with GET-PROPERTY-
and enclosing it in angle
brackets. The ActiveX control handle and the property parameters (if any) are
passed in the WITH
clause of the
PROCESS GUI
statement. The property value is received in the USING
clause of
the PROCESS GUI
statement.
This means: To get the value of a property that has parameters, you enter a statement
PROCESS GUI ACTION
<<GET-PROPERTY- propertyname>> WITH handlename
[parameter]
|
... USING
get-property-operand |
Example:
PROCESS GUI ACTION <<GET-PROPERTY-ItemHeight>> WITH #OCX-1 #ROW #COL USING #ITEMHEIGHT
Formats and length of the property parameters and the property value are checked at compiletime against the definition of the method, as it is displayed in the Component Browser.
To put the value of a property that has parameters, the name of
the corresponding PROCESS GUI
action is built by prefixing the
property name with PUT-PROPERTY-
and enclosing it in angle
brackets. The ActiveX control handle and the property parameters (if any) are
passed in the WITH
clause of the
PROCESS GUI
statement. The property value is passed in the USING
clause of the
PROCESS GUI
statement.
This means: To put the value of a property that has parameters, you enter a statement
PROCESS GUI ACTION
<<PUT-PROPERTY- propertyname>> WITH handlename
[parameter]
|
... USING
put-property-operand |
Example:
PROCESS GUI ACTION <<PUT-PROPERTY-ItemHeight>> WITH #OCX-1 #ROW #COL USING #ITEMHEIGHT
Formats and length of the property parameters and the property value are checked at compiletime against the definition of the method, as it is displayed in the Component Browser.
Methods of ActiveX controls can have optional parameters. This is
also true for parameterized properties. Optional parameters need not to be
specified when the method is called. To omit an optional parameter, use the
placeholder 1X in the PROCESS
GUI
statement. To omit n optional
parameters, use the placeholder nX.
In the following example it is assumed that the method
SetAddress
of the ActiveX control #OCX-1
has the parameters FirstName
, MiddleInitial
,
LastName
, Street
and City
, where
MiddleInitial
, Street
and City
are
optional. Then the following statements are correct:
* Specifying all parameters. PROCESS GUI ACTION <<METHOD-SetAddress>> WITH #OCX-1 FirstName MiddleInitial LastName Street City * Omitting one optional parameter. PROCESS GUI ACTION <<METHOD-SetAddress>> WITH #OCX-1 FirstName 1X LastName Street City * Omitting the optional parameters at end explicitly. PROCESS GUI ACTION <<METHOD-SetAddress>> WITH #OCX-1 FirstName MiddleInitial LastName 2X * Omitting the optional parameters at end implicitly. PROCESS GUI ACTION <<METHOD-SetAddress>> WITH #OCX-1 FirstName MiddleInitial LastName
Omitting a non-optional (mandatory) parameter results in a syntax error.
The GIVING
clause of the
PROCESS GUI
statement can be used as usual to handle error conditions. The error code can
either be caught in a user variable and then be handled, or the normal Natural
error handling can be triggered and the error condition be handled in an
ON ERROR
block.
Example:
DEFINE DATA LOCAL 1 #RESULT-CODE (N7) ... END-DEFINE ... * Catching the error code in a user variable: PROCESS GUI ACTION <<METHOD-RemoveItem>> WITH #OCX-1 #ROW #COL USING #RETURN GIVING #RESULT-CODE * * Triggering the Natural error handling: PROCESS GUI ACTION <<METHOD-RemoveItem>> WITH #OCX-1 #ROW #COL USING #RETURN GIVING *ERROR-NR ...
Special error conditions that can occur during the execution of ActiveX control methods are:
A method parameter, method return value or property value could not be converted to the data format expected by the ActiveX control. (These format checks are normally already done at compiletime. In these cases no runtime error can be expected. However, note that method parameters, method return values or property values defined as Variant are not checked at compiletime. This applies also for arrays and for those data types that can be mapped to several possible Natural data types.)
A COM or Automation error occurs while locating and executing a method.
The ActiveX control raises an exception during the execution of a method.
In these cases the error message contains further information provided by the ActiveX control, which can be used to determine the reason of the error with the help of the documentation of the ActiveX control.
Events sent by ActiveX controls can have parameters. In the controls event-handler sections, these parameters can be queried. Parameters passed by reference can also be modified. The events of an ActiveX control, the names and data types of the parameters and the fact if a parameter is passed by value or by reference is all displayed in the Component Browser.
Event parameters of an ActiveX control are addressed like
attributes of built-in controls. The attribute name is built by prefixing the
parameter name with PARAMETER-
and enclosing it in angle brackets.
Alternatively, parameters can be addressed by position. This means the
attribute name is built by prefixing the number of the parameter with
PARAMETER-
and enclosing it in angle brackets. The first parameter
of an event has the number 1, the second the number 2 and so on. These
attribute names are only valid inside the event handler of that particular
event.
In the following examples it is assumed that a particular event of
the ActiveX control #OCX-1
has the parameters KeyCode
and Cancel
. Then the event handler of that event might contain the
following statements:
* Querying a parameter by name: #PRESSEDKEY := #OCX-1.<<PARAMETER-KeyCode>> * Querying a parameter by position: #PRESSEDKEY := #OCX-1.<<PARAMETER-1>>
Parameters that are passed by reference can be modified in the
event handler. In the following example it is assumed that the
Cancel
parameter is passed by reference and is thus modifiable.
Then the event handler might contain the following statements:
* Modifying a parameter by name: #OCX-1.<<PARAMETER-Cancel>>:= TRUE * Modifying a parameter by position: #OCX-1.<<PARAMETER-2>>:= TRUE
To suppress or unsuppress an event of an ActiveX control at
runtime, modify the corresponding suppress event attribute of the control. The
name of the suppress event attribute is built by prefixing the event name with
SUPPRESS-EVENT-
and enclosing it in angle brackets. The events of
an ActiveX control are displayed in the
Component Browser.
The following example assumes that the ActiveX control
#OCX-1
has the event ColMoved
.
* Suppress the event. #OCX-1.<<SUPPRESS-EVENT-ColMoved>> := SUPPRESSED * Unsuppress the event. #OCX-1.<<SUPPRESS-EVENT-ColMoved>> := NOT-SUPPRESSED