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
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 )
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]
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:
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 )
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
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.
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
on IncomingEvent me, event, args
put event, args
on ConnectComplete me, args
pError = args
adStatus = args
pConnection = args
if ( adStatus 1 ) then alert pError.Description
on Disconnect me, args
adStatus = args
pConnection = args
on WillConnect me, args
ConnectionString = args
UserID = args
Password = args
Options = args
adStatus = args
pConnection = args
-- 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 = 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