Beispiel: Verwenden der externen API mit einem ActiveX-Container



In diesem Beispiel wird die Verwendung der externen API für den Datenaustausch zwischen ActionScript und einer Desktopanwendung mit einem ActiveX-Steuerelement veranschaulicht. In dem Beispiel wird weiterhin die Anwendung „Introvert IM“ verwendet, einschließlich des ActionScript-Codes und sogar derselben SWF-Datei. Deshalb wird auf eine erneute Beschreibung des Einsatzes der externen API in ActionScript verzichtet. Wenn Sie mit dem vorangegangenen Beispiel vertraut sind, erleichtert dies das Verständnis des aktuellen Beispiels.

Die Desktopanwendung in diesem Beispiel wurde mit Microsoft Visual Studio.NET in C# programmiert. Der Schwerpunkt liegt auf den spezifischen Techniken zur Verwendung der externen API mit dem ActiveX-Steuerelement. In diesem Beispiel wird Folgendes veranschaulicht:

  • Aufrufen von ActionScript-Funktionen aus einer Desktopanwendung, in der das Flash Player-ActiveX-Steuerelement ausgeführt wird

  • Empfangen von Funktionsaufrufen aus ActionScript und entsprechende Verarbeitung im ActiveX-Container

  • Verwenden einer Proxy-Klasse zum Verbergen des serialisierten XML-Formats, das in Flash Player für Nachrichten an ActiveX-Container verwendet wird

Die Anwendungsdateien für dieses Beispiel finden Sie unter www.adobe.com/go/learn_programmingAS3samples_flash_de. Die C#-Dateien der Anwendung „Introvert IM“ befinden sich im Ordner „Samples/IntrovertIM_CSharp“. Die Anwendung umfasst die folgenden Dateien:

Datei

Beschreibung

AppForm.cs

Die Hauptanwendungsdatei mit der Windows Forms-Benutzeroberfläche in C#.

bin/Debug/IntrovertIMApp.swf

Die in der Anwendung geladene SWF-Datei.

ExternalInterfaceProxy/ExternalInterfaceProxy.cs

Die Klasse, die als Wrapper um das ActiveX-Steuerelement für den Datenaustausch mit der externen Schnittstelle dient. Sie stellt Mechanismen zum Aufrufen von Funktionen sowie zum Empfangen von Funktionsaufrufen aus ActionScript bereit.

ExternalInterfaceProxy/ExternalInterfaceSerializer.cs

Die Klasse, mit der die Nachrichten aus dem XML-Format von Flash Player in .NET-Objekte konvertiert werden.

ExternalInterfaceProxy/ExternalInterfaceEventArgs.cs

Diese Datei definiert zwei C#-Typen (Klassen): eine benutzerdefinierte Delegate-Klasse und eine Ereignisargumentklasse, die von der ExternalInterfaceProxy-Klasse verwendet werden, um einen Listener über Funktionsaufrufe aus ActionScript zu benachrichtigen.

ExternalInterfaceProxy/ExternalInterfaceCall.cs

Diese Klasse ist ein Wertobjekt, mit dem ein Funktionsaufruf aus ActionScript an den ActiveX-Container mit Eigenschaften für den Funktionsnamen und die Parameter angegeben wird.

bin/Debug/IntrovertIMApp.swf

Die in der Anwendung geladene SWF-Datei.

obj/AxInterop.ShockwaveFlashObjects.dll,

obj/Interop.ShockwaveFlashObjects.dll

In Visual Studio .NET erstellte Wrapper-Bibliotheken, die für den Zugriff auf das Flash Player-ActiveX-Steuerelement (Adobe Shockwave® Flash) aus verwaltetem Code erforderlich sind.

Überblick über die C#-Anwendung „Introvert IM“

Diese Beispielanwendung stellt zwei Instant Messaging-Clientprogramme (eine in einer SWF-Datei und die andere mit Windows Forms erstellt) dar, die miteinander kommunizieren. Zur Benutzeroberfläche gehört eine Instanz des Shockwave Flash-ActiveX-Steuerelements, in die die SWF-Datei geladen wird, die den ActionScript-IM-Client enthält. Die Benutzeroberfläche umfasst auch mehrere Textfelder, die den Windows Forms-IM-Client bilden: ein Feld zum Eingeben von Nachrichten (MessageText), ein weiteres zum Anzeigen des Mitschnitts der zwischen den beiden Clients ausgetauschten Nachrichten (Transcript) und ein drittes (Status), das den im SWF-IM-Client festgelegten Verfügbarkeitsstatus angibt.

Einfügen des Shockwave Flash-ActiveX-Steuerelements

Um das Shockwave Flash-ActiveX-Steuerelement in die Windows Forms-Anwendung aufnehmen zu können, müssen Sie es zuerst zur Toolbox von Microsoft Visual Studio hinzufügen.

So fügen Sie das Steuerelement zur Toolbox hinzu:

  1. Öffnen Sie die Visual Studio-Toolbox.

  2. Klicken Sie in Visual Studio 2003 mit der rechten Maustaste auf den Bereich „Windows Forms“ oder in Visual Studio 2005 auf einen beliebigen Bereich. Wählen Sie in Visual Studio 2003 im Kontextmenü die Option „Elemente hinzufügen/entfernen“ aus (wählen Sie in Visual Studio 2005 die Option „Elemente...“ aus).

    Das Dialogfeld „Toolbox anpassen“ (2003) bzw. „Toolboxelemente auswählen“ (2005) wird angezeigt.

  3. Klicken Sie auf die Registerkarte „COM-Komponenten“, auf der alle auf dem Computer verfügbaren COM-Komponenten einschließlich des Flash Player-ActiveX-Steuerelements aufgeführt sind.

  4. Führen Sie einen Bildlauf bis zur Komponente „Shockwave Flash Object“ durch und wählen Sie sie aus.

    Wenn dieses Element nicht aufgeführt ist, überprüfen Sie, ob das Flash Player-ActiveX-Steuerelement auf dem Computer installiert ist.

Kommunikation zwischen ActionScript und dem ActiveX-Container

Die Kommunikation mit einer ActiveX-Containeranwendung über die externe API entspricht der Kommunikation mit einem Webbrowser, jedoch mit einem wichtigen Unterschied. Wie bereits beschrieben, werden bei der Kommunikation von ActionScript mit einem Webbrowser – zumindest soweit es Entwickler betrifft – die Funktionen direkt aufgerufen. Die Details der Formatierung von zwischen Player und Browser übergebenen Funktionsaufrufen und Rückgabewerten sind verborgen. Wenn die externe API jedoch für den Datenaustausch mit einer ActiveX-Containeranwendung eingesetzt wird, werden in Flash Player Nachrichten (Funktionsaufrufe und Rückgabewerte) in einem speziellen XML-Format an die Anwendung gesendet. Bei Funktionsaufrufen und Rückgabewerten aus der Containeranwendung wird dasselbe XML-Format erwartet. Entwickler der ActiveX-Containeranwendung müssen Code programmieren, mit dem dieses Format gelesen werden kann und mit dem Funktionsaufrufe und Rückgabewerte entsprechend formatiert werden.

Die C#-Beispielanwendung „Introvert IM“ enthält eine Reihe von Klassen, mit denen Sie die Formatierung von Nachrichten vermeiden können. Stattdessen können Sie beim Aufrufen von ActionScript-Funktionen und beim Empfangen von Funktionsaufrufen aus ActionScript die Standarddatentypen verwenden. Diese Funktionalität wird von der ExternalInterfaceProxy-Klasse und anderen unterstützenden Klassen bereitgestellt. Sie kann in allen .NET-Projekten eingesetzt werden, um die Kommunikation über die externe API zu erleichtern.

In den folgenden Codeabschnitten, die einen Auszug aus dem Hauptformular der Anwendung (AppForm.cs) darstellen, wird die vereinfachte Interaktion demonstriert, die mithilfe der ExternalInterfaceProxy-Klasse erreicht wird:

public class AppForm : System.Windows.Forms.Form 
{ 
    ... 
    private ExternalInterfaceProxy proxy; 
    ... 
    public AppForm() 
    { 
        ... 
        // Register this app to receive notification when the proxy receives 
        // a call from ActionScript. 
        proxy = new ExternalInterfaceProxy(IntrovertIMApp); 
        proxy.ExternalInterfaceCall += new ExternalInterfaceCallEventHandler(proxy_ExternalInterfaceCall); 
        ... 
    } 
    ...

In der Anwendung wird eine ExternalInterfaceProxy-Instanz mit dem Namen proxy deklariert und erstellt sowie ein Verweis auf das Shockwave Flash-ActiveX-Steuerelement übergeben, das sich in der Benutzeroberfläche (IntrovertIMApp) befindet. Anschließend wird die proxy_ExternalInterfaceCall()-Methode für den Empfang des vom Proxy gesendeten ExternalInterfaceCall-Ereignisses registriert. Dieses Ereignis wird von der ExternalInterfaceProxy-Klasse ausgelöst, wenn ein Funktionsaufruf aus Flash Player erfolgt. Durch Registrieren für dieses Ereignis im C#-Code werden von ActionScript stammende Funktionsaufrufe empfangen, und es kann auf sie reagiert werden.

Wenn ein von ActionScript ausgehender Funktionsaufruf eintrifft, empfängt die ExternalInterfaceProxy-Instanz (proxy) den Aufruf, konvertiert ihn aus dem XML-Format und benachrichtigt die Objekte, die Listener für das ExternalInterfaceCall-Ereignis der Proxy-Klasse registriert haben. Im Fall der AppForm-Klasse wird das Ereignis wie folgt mit der proxy_ExternalInterfaceCall()-Methode verarbeitet:

    /// <summary> 
    /// Called by the proxy when an ActionScript ExternalInterface call 
    /// is made by the SWF 
    /// </summary> 
    private object proxy_ExternalInterfaceCall(object sender, ExternalInterfaceCallEventArgs e) 
    { 
        switch (e.FunctionCall.FunctionName) 
        { 
            case "isReady": 
                return isReady(); 
            case "setSWFIsReady": 
                setSWFIsReady(); 
                return null; 
            case "newMessage": 
                newMessage((string)e.FunctionCall.Arguments[0]); 
                return null; 
            case "statusChange": 
                statusChange(); 
                return null; 
            default: 
                return null; 
        } 
    } 
    ...

In diesem Beispiel wird eine ExternalInterfaceCallEventArgs-Instanz mit dem Namen e an die Methode übergeben. Dieses Objekt hat wiederum eine FunctionCall-Eigenschaft, die eine Instanz der ExternalInterfaceCall-Klasse ist.

Eine ExternalInterfaceCall-Instanz ist ein einfaches Wertobjekt mit zwei Eigenschaften. Die FunctionName-Eigenschaft enthält den in der ActionScript-Anweisung ExternalInterface.Call() angegebenen Funktionsnamen. Wenn in ActionScript Parameter hinzugefügt wurden, werden diese in der Arguments-Eigenschaft des ExternalInterfaceCall-Objekts abgelegt. In diesem Fall besteht die Methode zur Ereignisverarbeitung einfach aus einer switch-Anweisung, die wie ein Verteiler funktioniert. Der Wert der FunctionName-Eigenschaft (e.FunctionCall.FunctionName) gibt an, welche Methode der AppForm-Klasse aufgerufen wird.

Die Verzweigungen der switch-Anweisung im vorangegangenen Codebeispiel veranschaulichen häufige Aufrufszenarien. Beispielsweise muss jede Methode entweder einen Wert an ActionScript zurückgeben (z. B. beim Aufruf der isReady()-Methode) oder andernfalls null (wie in den anderen Methodenaufrufen dargestellt). Der Zugriff auf von ActionScript übergebene Parameter wird beim Aufruf der newMessage()-Methode demonstriert (bei dem der Parameter e.FunctionCall.Arguments[0] übergeben wird, das erste Element des Arrays Arguments).

Das Aufrufen einer ActionScript-Funktion aus C# mithilfe der ExternalInterfaceProxy-Klasse ist sogar noch einfacher als das Empfangen von Funktionsaufrufen aus ActionScript. Verwenden Sie zum Aufrufen einer ActionScript-Funktion wie folgt die Call()-Methode der ExternalInterfaceProxy-Instanz:

    /// <summary> 
    /// Called when the "Send" button is pressed; the value in the 
    /// MessageText text field is passed in as a parameter. 
    /// </summary> 
    /// <param name="message">The message to send.</param> 
    private void sendMessage(string message) 
    { 
        if (swfReady) 
        { 
            ... 
            // Call the newMessage function in ActionScript. 
            proxy.Call("newMessage", message); 
        } 
    } 
    ... 
    /// <summary> 
    /// Call the ActionScript function to get the current "availability" 
    /// status and write it into the text field. 
    /// </summary> 
    private void updateStatus() 
    { 
        Status.Text = (string)proxy.Call("getStatus"); 
    } 
    ... 
}

Wie dieses Beispiel veranschaulicht, ähnelt die Call()-Methode der ExternalInterfaceProxy-Klasse sehr dem ActionScript-Gegenstück ExternalInterface.Call(). Der erste Parameter ist ein String: der Name der aufzurufenden Funktion. Alle weiteren Parameter (im Beispiel nicht dargestellt) werden ebenfalls an die ActionScript-Funktion übergeben. Wenn die ActionScript-Funktion einen Wert zurückgibt, wird dieser von der Call()-Methode zurückgegeben (wie im vorangegangenen Beispiel dargestellt).

Details der ExternalInterfaceProxy-Klasse

Die Verwendung eines Proxy-Wrappers um das ActiveX-Steuerelement ist nicht immer praktikabel, oder Sie möchten vielleicht eine eigene Proxy-Klasse programmieren (beispielsweise in einer anderen Programmiersprache oder für eine andere Plattform). Obwohl an dieser Stelle nicht auf alle Details zum Erstellen einer Proxy-Klasse eingegangen wird, ist es sicherlich lehrreich, den internen Aufbau der in diesem Beispiel verwendeten Proxy-Klasse zu verstehen.

Sie verwenden die CallFunction()-Methode des Shockwave Flash-ActiveX-Steuerelements, um mithilfe der externen API eine ActionScript-Funktion aus dem ActiveX-Container aufzurufen. Dies ist im folgenden Auszug aus der Call()-Methode der ExternalInterfaceProxy-Klasse dargestellt:

// Call an ActionScript function on the SWF in "_flashControl", 
// which is a Shockwave Flash ActiveX control. 
string response = _flashControl.CallFunction(request);

Im Codeauszug ist _flashControl das Shockwave Flash-ActiveX-Steuerelement. ActionScript-Funktionsaufrufe erfolgen mit der CallFunction()-Methode. Diese Methode erwartet einen Parameter (im Beispiel request). Dabei handelt es sich um einen String mit XML-formatierten Anweisungen, aus dem der Name der aufzurufenden ActionScript-Funktion und etwaige Parameter hervorgehen. Ein gegebenenfalls von ActionScript zurückgegebener Wert wird als XML-formatierter String kodiert und als Rückgabewert des CallFunction()-Aufrufs zurückgesendet. In diesem Beispiel wird dieser XML-String in der Variablen response gespeichert.

Das Empfangen eines Funktionsaufrufs aus ActionScript besteht aus mehreren Schritten. Durch Funktionsaufrufe aus ActionScript wird mit dem Shockwave Flash-ActiveX-Steuerelement ein FlashCall-Ereignis ausgelöst. Bei einer Klasse (beispielsweise der ExternalInterfaceProxy-Klasse), die Aufrufe aus einer SWF-Datei empfangen soll, muss deshalb eine Ereignisprozedur für dieses Ereignis definiert werden. Bei der ExternalInterfaceProxy-Klasse trägt die Ereignisprozedurfunktion den Namen _flashControl_FlashCall() und wird im Klassenkonstruktor wie folgt als Listener für das Ereignis registriert:

private AxShockwaveFlash _flashControl; 
 
public ExternalInterfaceProxy(AxShockwaveFlash flashControl) 
{ 
    _flashControl = flashControl; 
    _flashControl.FlashCall += new _IShockwaveFlashEvents_FlashCallEventHandler(_flashControl_FlashCall); 
} 
... 
private void _flashControl_FlashCall(object sender, _IShockwaveFlashEvents_FlashCallEvent e) 
{ 
    // Use the event object's request property ("e.request") 
    // to execute some action. 
    ... 
    // Return a value to ActionScript; 
    // the returned value must first be encoded as an XML-formatted string. 
    _flashControl.SetReturnValue(encodedResponse); 
}

Das Ereignisobjekt (e) hat eine request-Eigenschaft (e.request). Dabei handelt es sich um einen String, der im XML-Format Informationen über den Funktionsaufruf, z. B. den Funktionsnamen und die Parameter, enthält. Mithilfe dieser Informationen kann im Container ermittelt werden, welcher Code ausgeführt werden soll. Mit der ExternalInterfaceProxy-Klasse wird die Anforderung aus dem XML-Format in ein ExternalInterfaceCall-Objekt konvertiert, das dieselben Informationen in einer besser zugänglichen Form bereitstellt. Mithilfe der SetReturnValue()-Methode des ActiveX-Steuerelements wird ein Funktionsergebnis an den aufrufenden ActionScript-Code zurückgegeben. Wieder muss der Ergebniswert in das von der externen API verwendete XML-Format kodiert werden.

Bei der Kommunikation zwischen ActionScript und einer Anwendung, in der ein Shockwave Flash-ActiveX-Steuerelement ausgeführt wird, wird zum Kodieren der Funktionsaufrufe und Rückgabewerte ein spezielles XML-Format verwendet. In der C#-Beispielanwendung „Introvert IM“ ermöglicht es die ExternalInterfaceProxy-Klasse, dass im Code des Anwendungsformulars direkt auf die an ActionScript gesendeten oder von ActionScript empfangenen Werte zugegriffen werden kann und die Details des von Flash Player verwendeten XML-Formats nicht beachtet werden müssen. Dazu werden in der ExternalInterfaceProxy-Klasse die Methoden der ExternalInterfaceSerializer-Klasse verwendet, um die XML-Nachrichten in .NET-Objekte umzuwandeln. Die ExternalInterfaceSerializer-Klasse verfügt über vier öffentliche Methoden:

  • EncodeInvoke(): Diese Methode kodiert einen Funktionsnamen und ein mit Argumenten gefülltes ArrayList-C#-Objekt in das entsprechende XML-Format.

  • EncodeResult(): Diese Methode kodiert einen Rückgabewert in das entsprechende XML-Format.

  • DecodeInvoke(): Diese Methode dekodiert einen Funktionsaufruf aus ActionScript. Die request-Eigenschaft des FlashCall-Ereignisobjekts wird an die DecodeInvoke()-Methode übergeben. Der Aufruf wird dann in ein ExternalInterfaceCall-Objekt umgewandelt.

  • DecodeResult(): Diese Methode dekodiert den als Rückgabewert nach dem Aufrufen einer ActionScript-Funktion empfangenen XML-String.

Mit diesen Methoden werden C#-Werte in das XML-Format der externen API kodiert bzw. XML-Werte in C#-Objekte dekodiert. Weitere Informationen zum vom Flash Player verwendeten XML-Format finden Sie unter XML-Format der externen API.