F# で Flex で ExternalInterface

2か月ぶりって。

まず mxml 書いて、

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
        xmlns:mx="http://www.adobe.com/2006/mxml"
        layout="absolute" height="120" width="210"
        creationComplete="onApplicationCreationComplete(event);">

    <mx:Canvas height="100%" width="100%">
        <mx:HBox x="10" y="10">
            <mx:TextInput id="txtVal1" width="50" text="1"/>
            <mx:Label text="+"/>
            <mx:TextInput id="txtVal2" width="50" text="2"/>
            <mx:Button id="btnRun" label="Run"/>
        </mx:HBox>
    </mx:Canvas>
    
    <mx:Script>
        <![CDATA[
            import mx.controls.Alert;
            import mx.events.FlexEvent;
            
            private function onApplicationCreationComplete(event:FlexEvent):void {
                ExternalInterface.addCallback("onFlashCallReceive", onFlashCallReceive);
                btnRun.addEventListener(FlexEvent.BUTTON_DOWN, onBtnCalcButtonDown);
            }
            
            private function onBtnCalcButtonDown(event:FlexEvent):void {
                ExternalInterface.call("sum", parseInt(txtVal1.text), parseInt(txtVal2.text));
            }
            
            private function onFlashCallReceive(value:int):void {
                Alert.show(value.toString());
            }
        ]]>
    </mx:Script>
</mx:Application>

swf にする。

C:\work>mxmlc eit.mxml

次に、aximp で Flash Player の dll を生成する。

C:\work>aximp C:\WINDOWS\system32\Macromed\Flash\Flash10a.ocx
Generated Assembly: C:\work\stdole.dll
Generated Assembly: C:\work\ShockwaveFlashObjects.dll
Generated Assembly: C:\work\AxShockwaveFlashObjects.dll

で、fs 書いて、

#light

open System
open System.Drawing
open System.Windows.Forms
open System.Xml

open AxShockwaveFlashObjects

let main () =
    let form = new Form()
    form.Text <- "ExternalInterface Test"
    form.FormBorderStyle <- FormBorderStyle.FixedSingle
    form.ClientSize <- new Size(210, 120)
    form.Location <- new Point(0, 0)

    let flash:AxShockwaveFlash = new AxShockwaveFlash()
    flash.FlashCall.Add(fun (evt:_IShockwaveFlashEvents_FlashCallEvent) ->
        let doc: XmlDocument = new XmlDocument()
        doc.LoadXml(evt.request)

        let name:string = doc.SelectSingleNode("/invoke/@name").Value
        match name with
            | "sum" ->
                let mutable value:int = 0
                let nodes:XmlNodeList = doc.SelectNodes("//arguments/number/text()")
                for i = 0 to nodes.Count - 1 do
                    value <- value + Int32.Parse(nodes.Item(i).Value)
                done
                let resp:string =
                    "<invoke name=\"onFlashCallReceive\" returntype=\"xml\">" +
                    "<arguments><number>" + value.ToString() + "</number></arguments>" +
                    "</invoke>"
                let ret:string = flash.CallFunction(resp)
                ()

            | _ ->
                ()
        )
    form.Controls.Add(flash)
    form.Visible <- true

    flash.Movie <- "c:\\work\\eit.swf"
    flash.ClientSize <- new Size(210, 120)
    flash.Location <- new Point(0, 0)
    flash.Play()

    Application.Run(form)

[<STAThread>]
do main()

実行する。

C:\work>fsi --quiet --exec -r AxShockwaveFlashObjects.dll eit.fs

足し算してるだけ。

ExternalInterface のデータフォーマットはこんなん。
例 : ActiveX コンテナに対する External API の使用 -- Flex 2.01 が詳しいかな。

<invoke name="onFlashCallReceive" returntype="xml">
    <arguments>
        <number>3</number>
    </arguments>
</invoke>