C#のアプリ(Windowsフォームアプリケーション)にswfを埋め込み方法を取り上げたので、今回はその間をExternalInterfaceで通信する方法を説明する。
昔は、fscommand()とSetVariableを使うやり方が多かったみたいだけど、今はExternalInterfaceがいいようだ。Adobeもお勧めしている。
ここで説明する内容は次の二つのページを参考にしている。
ActiveX コンテナでの外部 API の使用
http://livedocs.adobe.com/flex/3_jp/html/help.html?content=19_External_Interface_10.html
C#とFlashの連携その5
http://createwave.blog104.fc2.com/?no=128
より自分的に理解しやすい形で紹介してみる。
以前のエントリーC#のアプリにFlash(swf)を埋め込む。は理解していることを前提にしている。
◆はじめに
作例としては、C#側のフォームとswf側のフォームでチャットのようにメッセージを送受信するものだ。
上部がエリアがC#のフォーム。下部のピンクのエリアがswfのフォーム。
Adobeのサンプルと同じ趣旨なのだが、Adobeのサンプルは古いタイプのプロジェクトファイルだからか、手元のMicrosoft Visual C# 2010 Expressだと、変換したりアラート類がいろいろ出たりで、安心してリファレンスとして扱いにくい。また、本筋じゃないところでコードが増えているようにも見えたので、必要な要素に絞った作例で説明する。
FlashからはExternalInterfaceを用いるので、JSとの通信と全く代わりが無い。そのまま流用できるほどだ。
次の枠内のもので、実際に同じswfとjsでの通信ができていることが確認できる。
ただ、C#側にはFlashとの通信用のExternalInterfaceはデフォルトでは無いので、設定が必要だ。
◆ExternalInterfaceを使うための準備
C#とFlashでExternalInterfaceを用いて通信するためのクラスがAdobeによって提供されているので、手に入れて、使える状態にする。
・C#用のクラスを手に入れる。
Flash Developer CenterのSamplesのページ
Flash CS3 Professional samplesの項目にリンクされているProgramming_ActionScript3.0_samples.zipをダウンロードする。
http://www.adobe.com/devnet/flash/samples.html
展開して、IntrovertIM_CSharpの中のExternalInterfaceProxyから、次の4ファイルをコピーする。
ExternalInterfaceCall.cs
ExternalInterfaceCallEventArgs.cs
ExternalInterfaceProxy.cs
ExternalInterfaceSerializer.cs
・使える状態にする。
自分で作ったWindowsフォームアプリケーションディレクトリ内のProgramp.csと同階層にペーストする。
「ソリューション エクスプローラー」のメニュー上、「すべてのファイルを表示」ボタンを選択。
ペーストした4ファイルがソリューションエクスプローラーに表示される。
選択して、右クリックで「プロジェクトに含める」を選択。
これで準備完了。
◆Flash側
ここは、ブラウザ上のJS向けの書き方と全く同じ。
・C#への送信
次のようにC#上の関数名(”fromAS”)と引数(_nameField.text, message)を指定する。
1 2 |
// 外部(JS,C#)関数の呼び出し ExternalInterface.call("fromAS", _nameField.text, message); |
ただし、実際にはJSと違って、C#上のfromASという関数を直接実行できるわけではない。
・C#からの受信
コールバック関数の登録もJSと同じ。
1 2 |
// 外部(JS,C#)から呼ばれるコールバック関数の登録 ExternalInterface.addCallback ("asFunction", callbackFunction); |
C#側からは「asFunction」を指定すると、AS内のcallbackFunctionが実行される。
・ソースコード全体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
package { import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.external.ExternalInterface; import flash.text.TextField; /** * ... * @author umhr */ [SWF(width = 400, height = 200, backgroundColor = 0xFFDDDD, frameRate = 30)] public class Main extends Sprite { private var _textField:TextField = new TextField(); private var _nameField:TextField = new TextField(); private var _messageField:TextField = new TextField(); public function Main():void { if (stage) init(); else addEventListener(Event.ADDED_TO_STAGE, init); } private function init(e:Event = null):void { removeEventListener(Event.ADDED_TO_STAGE, init); // entry point addTextField(); // ボタン var btn:Sprite = new Sprite(); btn.graphics.beginFill(0xFFFF9999); btn.graphics.drawRoundRect(0, 0, 75, 21, 8, 8); btn.graphics.endFill(); btn.x = 325; btn.y = 174; btn.addEventListener(MouseEvent.CLICK, btn_click); addChild(btn); // 外部(JS,C#)から呼ばれるコールバック関数の登録 try { ExternalInterface.addCallback ("asFunction", callbackFunction); _textField.text = "コールバック関数の登録ができました。\n"; }catch (error:Error) { _textField.text = "コールバック関数の登録ができませんでした。\n"; } } /** * 外部(JS,C#)から呼ばれるコールバック関数 * @param ...args */ private function callbackFunction(...args):void { addText(args[0], args[1]); } /** * 外部(JS,C#)の関数の呼び出し * @param e */ private function btn_click(e:MouseEvent):void { try { var message:String = _messageField.text; if (message == "") { // 何もないと、外部側でエラーになる場合がある。 message = " "; } // 外部(JS,C#)関数の呼び出し ExternalInterface.call("fromAS", _nameField.text, message); // テキストフィールドにも書き込み。 addText(_nameField.text, _messageField.text); _messageField.text = ""; }catch (error:Error) { _textField.appendText("外部(JS,C#)の関数の呼び出しができませんでした。\n"); } } /** * テキストフィールドを作ってaddします。 */ private function addTextField():void { // テキストフィールド _textField.border = true; _textField.width = 399; _textField.height = 170; addChild(_textField); // 名前 _nameField.border = true; _nameField.width = 85; _nameField.height = 20; _nameField.y = _textField.height + _textField.y + 4; _nameField.type = "input"; _nameField.text = "Flash Program"; addChild(_nameField); // メッセージ _messageField.border = true; _messageField.width = 230; _messageField.height = 20; _messageField.x = _nameField.width + _nameField.x + 4; _messageField.y = _nameField.y; _messageField.type = "input"; _messageField.text = "Hello from Flash!"; addChild(_messageField); } /** * テキストフィールドに書き込みをします。 * @param name * @param message */ private function addText(name:String, message:String):void { _textField.appendText(name + ":" + message + "\n"); } } } |
◆C#側
先日の(C#のアプリにFlash(swf)を埋め込む。)と同じ要領で、Form1.csファイルを改変する。
ExternalInterfaceのクラスを使うために、宣言をする。
1 |
using Flash.External; |
まずは、ExternalInterfaceProxyをつくり、
1 |
private ExternalInterfaceProxy proxy; |
どのswfと送受信するためのproxyかを登録する。
1 2 |
// どのswfと送受信するためのproxyかを登録する。 proxy = new ExternalInterfaceProxy(axShockwaveFlash1); |
・ASからの受信
1 2 |
// ASから呼ばれた時に実行する関数を登録する。 proxy.ExternalInterfaceCall += new ExternalInterfaceCallEventHandler(proxy_ExternalInterfaceCall); |
実行される関数は次のように書く。返り値はobjectにしないといけないみたい。voidにしてreturnを消したらエラーが出た。
1 2 3 4 5 6 7 8 9 10 |
private object proxy_ExternalInterfaceCall(object sender, ExternalInterfaceCallEventArgs e) { // デバッグ用。呼ばれた関数名。 System.Diagnostics.Debug.WriteLine(e.FunctionCall.FunctionName); // テキストボックスに書き込みへ。 addText((string)e.FunctionCall.Arguments[0], (string)e.FunctionCall.Arguments[1]); return null; } |
AS上で指定した関数名は「e.FunctionCall.FunctionName」で取得できる。その名前の関数が実行されるわけではない。
どんな名前を指定しても、C#上で登録したイベントハンドラー(ここではproxy_ExternalInterfaceCall)が実行されるだけだ。
・ASへの送信
ASのExternalInterface.callと全く同じ書式。AS上の関数名(”asFunction”)と、引数(textBox1.Text, textBox2.Text)を指定する。
1 2 |
// AS上の関数を引数つきで実行 proxy.Call("asFunction", textBox1.Text, textBox2.Text); |
・ソースコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using Flash.External; namespace WindowsFormsApplication1 { public partial class Form1 : Form { private ExternalInterfaceProxy proxy; public Form1() { InitializeComponent(); // swfを読み込んで配置。 String swfPath = System.IO.Directory.GetCurrentDirectory() + "\\example.swf"; axShockwaveFlash1.LoadMovie(0, swfPath); // どのswfと送受信するためのproxyかを登録する。 proxy = new ExternalInterfaceProxy(axShockwaveFlash1); // ASから呼ばれた時に実行する関数を登録する。 proxy.ExternalInterfaceCall += new ExternalInterfaceCallEventHandler(proxy_ExternalInterfaceCall); } #region ASから呼ばれると、実行される関数。 private object proxy_ExternalInterfaceCall(object sender, ExternalInterfaceCallEventArgs e) { // デバッグ用。呼ばれた関数名。 System.Diagnostics.Debug.WriteLine(e.FunctionCall.FunctionName); // テキストボックスに書き込みへ。 addText((string)e.FunctionCall.Arguments[0], (string)e.FunctionCall.Arguments[1]); return null; } #endregion #region AS上の関数を呼び出します。 private void button1_Click(object sender, EventArgs e) { // AS上の関数を引数つきで実行 proxy.Call("asFunction", textBox1.Text, textBox2.Text); // テキストボックスに書き込みへ。 addText(textBox1.Text, textBox2.Text); textBox2.Text = ""; } #endregion #region テキストボックスに書き込みます。 private void addText(string name, string message) { textBox3.Text += name + ":" + message + System.Environment.NewLine; } #endregion } } |
◆ソースコード
AS
C#
WindowsFormsApplication2.zip
(このzip圧縮ファイルにはExternalInterfaceのクラスファイルは同梱されていない。上の説明を参考にAdobeのサンプルからダウンロードして補完する必要がある)
1 Comment
[…] C#のアプリに埋め込んだswfとの通信(ExternalInterface) […]