How to invoke the methods of an ActiveX control

To invoke a method of an ActiveX control on a WS window, you first need a “handle” for it, also known as an “oref”. Think of this as a pointer to the control. Within the control’s own Action Logic (AL) you can use the macro %%I (that’s a capital “i”). Outside the control’s AL the macro is not available, so if you need to invoke the method elsewhere (for example, on the Push event of a Button on your window), place an oref into an M local. A good place is in the ActiveX control’s Create logic:

ZSET MyCtl=%%I

Note the use of ZSET, which copies orefs. Don’t NEW MyCtl within the Create logic, else it’ll vanish as soon as the AL section quits.

It’s good practice to tidy this variable up in the matching Destroy section:

KILL MyCtl

Now when you want to invoke a method, you have a starting-point. Next question is, do you care about the return-value (if any) of the method? If you do, the syntax for a parameterless method called MyMethod would be:

SET rslt=MyCtl.MyMethod

or, if the method returns an object,

ZSET orslt=MyCtl.MyMethod

Naturally, if this is being done within the control’s own AL, you can use %%I instead:

SET rslt=%%I.MyMethod

When the return-value of the method is not needed, you can use:

DO MyCtl.MyMethod

To pass parameters to the method, list them in the natural way:

DO MyCtl.MyMeth2($H+1,var)

As an alternative to positional parameters, you can use named parameters. Though less efficient, it may improve legibility of code, and can be handy in skipping optional parameters:

DO %%I.MyMeth6(Sixth:=-1,Third:=var)

Now, how to handle output (or bi-directional) parameters? As an Mster might expect, you use the dot-prefix to pass a variable by reference. To use a real-world example:

DO F1Book1.GetSelection(nSel,.pRow1,.pCol1,.pRow2,.pCol2)

Of course, the variable F1Book1 must have been ZSET to %%I for the control, and nSel to the input value. But what about the four p-variables? In this case, the method doesn’t expect any input values on these parameters, but does want them to be of type Long. The notion of variable type is foreign to M, but MSM implements some simple rules when interfacing to COM objects such as ActiveX controls. When passing a variable by-reference as a method parameter, the nature of the initial contents of the variable dictate the type it’s passed as. If the variable contains a string, it’s passed as a String (technically, VT_BSTR). If it’s set to an integer, it’s passed as a Long (VT_I4), and if to a fractional number, as a Double (VT_R8). If it’s undefined it’s passed as omitted (VT_ERROR). If the M variable contained an oref it’s passed as an Object (VT_DISPATCH).

So in this case, the following is required before the method call:

SET (pRow1,pCol1,pRow2,pCol2)=0

Unfortunately, if your method requires another type of by-ref parameter, such as Integer (VT_I2) or Single (VT_R4) then you’re likely to get a “Type mismatch” error when you try to invoke the method.