A list of products available on this site
Documentation for XtraMania's xtras
Prices and links to the online store
Xtras, PDFs, samples
Have a question? Ask us!
Logo. www.xtramaina.com  
Home Search E-mail
ActiveCompanion Usage/Wrappers/Automation

ActiveCompanionSet xtras for Macromedia Director

Automation object wrapper

Automation object wrapper is a key component of VbScriptXtra. Wrapper object keeps the pointer to the real Automation object. When Lingo calls any method or property from wrapper object it passes it to the wrapped Automation object providing necessary type casting and error checking support. Automation object wrapper is created automatically by typecasting routines when IDispatch value is detected.

To explicitly create this wrapper use xtra-level CreateObject or GetObject method:
objAuto = xtra("VbScriptXtra").CreateObject( strProgId )

Most of methods and properties called from the wrapper are simply passed to the wrapped Automation object.

Use Interface() method to get the type library information of the wrapped Automation object via ObjectBrowser xtra.
vb = xtra( "VbScriptXtra" )
w = vb.CreateObject( "Word.Application" )
w.visible = true
put w.documents.Interface()

Use GenEnum( name ) method to get the value of named constant from wrapped object type library.
Vb = xtra("VbScriptXtra")
ppt = vb.CreateObject("PowerPoint.Application")
p = ppt.presentations.Add()
s = p.Slides.Add( 1, #ppLayoutBlank )
-- or
s = p.Slides.Add( 1, p.GetEnum(#ppLayoutBlank) )

To handle events provided by the wrapped automation object use EventsHandler property. See using events with ADO sample here.

Collection enumeration support is available via special __NewEnum property.
w = vb.GetObject("Word.Application")
col = w.Documents.__NewEnum
repeat with i = 1 to col.Count
  doc = col[i]
  put doc.Name
end repeat

Underscore Handling

Macromedia Director (D7, D8, and D8.5) sometimes behaves strangely with certain names. Director does not allow some names to be used as properties or method names. In Director MX and MX 2004 this problem seems to be fixed, although calling Delete method may not be passed to the xtra correctly.

To workaround this issue Automation wrapper at first tries to see whether wrapped object knows passed name. If so, it is processed. If it does not know it and the name starts with underscore '_', wrapper removes the first underscore and tries again.

Currently noticed names are: 'Delete' (D7, D8, and D8.5, MX) and 'Append' (D8.5).
Attempt to invoke Delete method of the wrapped Automation object generates a Lingo error before Delete is even passed to the xtra (D7, D8, D8.5, MX). The same way behaves D8.5 with Append method. To eliminate this problem use:

VbScriptXtra will remove the first underscore before passing method name to the wrapped Automation object. So methods are called correctly.

Named Method's Arguments

Lingo does not support named arguments as Visual Basic does, but starting with VbScriptXtra 2.3.3 you may use syntax very similar to VB named arguments. Simply place arguments into a property list. In this case VbScriptXtra will treat them as named arguments.

For example in VB:
obj.SomeMethod NameOfSomeArg:="SomeValue"

In Lingo just put named arguments into a property list:
obj.SomeMethod( [ #NameOfSomeArg:"SomeValue" ] )

Named and ordinal arguments can be mixed similar to VB, but ordinal arguments have to come first:
obj.SomeMethod( 1, 2, [ #NameOfSomeArg:"SomeValue" ] )

Note that property name will be checked against method argument names according to object's type definition. Lingo error 'Out of range' will be raised by VbScriptXtra in case invalid property name is used in named arguments property list.

Passing Parameters by Reference

VbScriptXtra Automation wrappers support arguments passed by reference, although it requires some special conventions. Lingo passes simple type values by value, but automation objects sometimes rely on arguments passed by reference. VbScriptXtra wrapper accepts parent script instances as method arguments. Once wrapper encounters such argument it will use its 'Value' property as an actual argument of the automation object's method. Then after method is executed, wrapper will put the updated argument value to 'value' property of the parent script instance.

So, if you expecting modified argument value you will have to create a simple parent script instance, set its value property with actual argument value, use that instance as an argument to wrapper object's method and then get the updated value from that instance. Most automation objects' method do not use arguments passed by reference, but sometimes, there is no other way.

Starting with VbScriptXtra 2.3.3 there is an alternative approach. It is based on passing named arguments within property list. In this case VbScriptXtra will refresh arguments that are expected to be references. After calling some method arguments property list will contain updated values.

args = [ #NameOfSomeArg:"SomeValue" ]
obj.SomeMethod( args )
put args

Optional and Missing Method's Arguments

Optional and missing arguments are supported by VbScriptXtra but Lingo requires you to use VOID value to indicate missing argument in the middle of the parameters list. Missing arguments in the end of the arguments list may be safely skipped. Default values will be used by automation object.
Also you may use named arguments syntax to avoid using a lot of VOIDs if your method needs only 5th argument and does not need others.

Using Wrapper Instance as First Argument of a Method

Take care while passing VbScriptXtra wrapper instance as the first argument to a movie handler. This may cause problems with some automation objects.

The problem arises from Lingo supporting both original and dot syntax. When Lingo interpreter encounters a method call, it checks whether its first argument is an object instance. So it tries to invoke a method of that object with the same name. If this call fails Lingo searches for a movie handler with this name and calls it if successful.

VbScriptXtra wrapper instance accepts any method name and tries to pass it to the wrapped automation object. Most of automation objects support a fixed set of methods, so the wrapper is capable to find out whether wrapped object supports the particular method or not. Such objects do not cause problems and are correctly passed to the movie handler if they do not support the same method.

There is at least one automation object, which behaves differently. It is ADODB.Connection object. Its instances accept any method names (not only supported directly), since Connection object may try to execute the stored database procedure, which may exist in database. If stored procedure exists it is executed, otherwise it generates corresponding error. This behavior does not allow VbScriptXtra wrapper to know whether such automation object supports particular name or not.

So, avoid passing wrapper instances as the first argument of movie handlers, since you may unintentionally call a method of this object instead of your movie handler.

Cascading Methods and Properties in Director 7

Director 7 has a bug in Lingo interpreter, which requires placing extra brackets to access properties of an object returned by some method. For example, the following statement will generate Lingo error.
put objAuto.someMethod().someProp -- Lingo error here

To avoid it you have to bracket method call:
put (objAuto.someMethod()).someProp -- Ok

Director 8 and later do not have this problem.

Using Square Brackets

When calling method with single argument or accessing indexed property with single index, it is possible to use either normal or square brackets. For example following Lingo syntax is possible with VbScriptXtra wrappers:
put rst.fields["FiledName"].Value -- works in D7 too

put rst.fields("FiledName").Value -- does not work in D7, see above

Unicode support

Every VbScriptXtra's wrapper object has special properties that affects on handling text data during typecasting operations. COM Automation internally works with Unicode text. So the xtra has to translate it for Director into MBCS there and back.

By default this conversion uses the code page of the default locale set as locale for non-Unicode applications in Windows. The CodePage property of the object defines the specific code page used for MBCS translation for this object.

In certain cases it may be useful to handle Unicode directly. VbScriptXtra v2.3 provides special mode for that. If UnicodeAsBinaryMode is set for the object, then typecasting routines will wrap Unicode data with Binary object without any Unicode to MBCS translation.

Both properties are inherited from parent objects. See more details about handling Unicode in Director here.

Handling events

Some Automation objects can provide feedback via so-called events. Events usually used to inform clients about anything or to ask whether server should or should not do something. For example Microsoft Word notifies via events that document is about to be closed allowing event's handler to prevent closing of the document if time for it has not come yet.

VbScriptXtra's Automation wrapper provides EventsHandler property. Assign it either sprite reference (it is useful for ActiveX visual controls) or parent script instance to handle object's events. Use ObjectBrowser to see whether particular object provides events.

Setting this property to a parent script instance or sprite reference makes the wrapper object to connect to the event source and start listening for events. Once some event occurs, wrapper object tries to call the parent script instance with that event.

Parameters to event handlers are passed by using property lists. This is done to allow event handlers to operate with parameters passed by reference.

For every event attached script instance is called twice. At first wrapper object tries to call the handler with the event name.
on EventName me, lstArgs
  put "EventName:" && lstArgs

Then IncomingEvent handler is called. Note: lstArgs coming to this handler might be modified by the previous handler (if any).
on IncomingEvent me, symEvent, lstArgs
  put symEvent, lstArgs

It is up to developer to choose which handling method to use. Both handlers are always called. If there is no handler to handle the event it is ignored.

The sample demonstrates using events with ADODB.Connection object.

-- *******************************************************
-- Here is the code for EventHandler parent script

on new me
  return me

on IncomingEvent me, event, args
  put event, args

on ConnectComplete me, args
  pError = args[1]
  adStatus = args[2]
  pConnection = args[3]
  put "ConnectComplete"
  if ( adStatus 1 ) then alert pError.Description

on Disconnect me, args
  adStatus = args[1]
  pConnection = args[2]
  put "Disconnect"

on WillConnect me, args
  ConnectionString = args[1]
  UserID = args[2]
  Password = args[3]
  Options = args[4]
  adStatus = args[5]
  pConnection = args[6]
  put "WillConnect"
  -- Creating new connection string
  -- Microsoft Jet provider for MS Access databases
  cnnStr = "Provider=Microsoft.Jet.OLEDB.4.0;"
  cnnStr = cnnStr & "Data Source=D:TempTestDB.mdb;"
  cnnStr = cnnStr & "Mode=Read|Write;"
  -- return it to the connection object via referenced parameter
  args[1] = cnnStr

-- End of the code for EventHandler parent script
-- *******************************************************

Name this script as "ConnectionEvents". Then try to execute following lines right in Director's messages window.
Vb = xtra("VbScriptXtra")

-- Setting debug mode to true

-- Creating an instance of the ADODB.Connection object
cnn = vb.CreateObject("ADODB.Connection")

-- Creating an instance of the events handler parent script
evnts = new( script("ConnectionEvents") )

-- Attaching handler to a wrapper
cnn.EventsHandler = evnts

-- Opening connection without explicitly specifying connection params
-- Connection string should be set by the events handler

-- Here we can do something with open connection
cnn.Execute("Some SQL query")

-- Now just close connection

Site homeSearchContact author © Eugene Shoustrov. www.xtramania.com