看过前面的文章的人,看到这个标题后可能觉得很眼熟,是的,我前面也写过Flash与C#程序进行交互的例子,不过,前面的例子注重于开发网络应用程序,在没有服务器的机器上面,就没有什么用了。今天我的这个例子,是让Flash嵌入C#窗体应用程序中,然后双方进行通信。
最近一段时间,项目经理想让我用Flash做一个读取数据库的程序出来,又不能使用服务器,而我前面所讲的那些技术,除了直接读取本地文件的那个例子以外,基本都需要通过服务器来实现交互的。这个和项目经理的要求不符合,去掉,而读取本地文件,项目经理也不同意。悲剧……
于是我就在网上寻找Flash直接读取数据库的例子,果然,还真被我找到一个,不过这个是用Flash里面的Socket写的,这个例子,在本地直接打开时很正常,但是一旦嵌入网页或者其他程序,就会什么也不显示,弄的我很郁闷,最后我上网查了一些资料,才知道这个是由于Flash的安全沙箱造成的,因此,这个方法也不符合要求,虽然项目经理就喜欢这个方法,但是被我否决了。
虽然否决了,但是这个项目不能就这么放着啊,不甘心半途而废,所以这两天就在网上找了很多资料,最终,被我找出来一个可以直接通信的方法,就是ExternalInterface,这个Adobe公司提出的和外部的通信接口,在网上很多资料里面都是和JS进行网页通讯的,所以我一直没有注意这个东西,直接导致我转了很大的一个圈,浪费时间和精力。所以今天就写一下我的心得吧,希望能帮助到各位!
ExternalInterface 类允许 Flash 播放器以异步的方式与宿主程序进行通信,宿主程序一般指的是Web 浏览器(也可以是其他应用程序,比如C#窗体应用程序)。
ExternalInterface 支持以下浏览器:
Internet Explorer 5.0+ (Windows)
Netscape 8.0+ (Windows and Mac OS X)
Mozilla 1.7.5+ (Windows and Mac OS X)
Firefox 1.0+ (Windows and Mac OS X)
Safari 1.3+ (Mac OS X)
ActionScript调用JavaScript(C#,Java,PHP等)函数,可使用ExternalInterface.call()。该方法采用异步调用JS(C#,Java,PHP等)函数机制。用法:ExternalInterface.call(JS方法名:string[,参数1:*,参数2:*……])。如果JS函数有返回值,可用变量存储:如var str:String = ExternalInterface.call(“jsFunction”);
可以用ExternalInterface.available查看浏览器是否支持,若不支持,可使用navigateToURL()方法。
JavaScript(C#,Java,PHP等)调用ActionScript函数:使用ExternalInterface.addCallback()注册AS函数,然后在JS端进行调用。用法:ExternalInterface.addCallback(被调用函数对JS的别名:string,被调用函数:function)。
如:ExternalInterface.addCallback(“helloWordAS”,helloWord);
上面是对这个函数的详细解释,具体的还有一些属性可以在AS3帮助文档中找到。看完上面的,我们就可以开始Flash和C#窗体应用程序的通信之旅了。
今天我的这个例子其实是上面项目经理要求我做的程序的简化版。要求是从数据库中读取数据,然后将这些数据传递给Flash程序,由Flash程序进行解析后根据要求将一些数据和图像显示在舞台上。具体的数据和需要显示的图像根据需求确定。
首先,我们来建立一个Flash应用程序。
打开Flash CS4,新建一个Flash文件(Action Script 3.0),取名为showPic.fla,保存。然后,按Ctrl+N,新建一个Action Script文件,保存在刚刚Flash文件保存的同级目录,取名为ShowPic.as。接着,在ShowPic.as里面写如下代码:
package{//导入类
import flash.display.MovieClip;import flash.external.ExternalInterface; //这个是和C#程序通讯的关键
import flash.text.*;import flash.utils.setInterval;import flash.display.StageAlign;import flash.display.StageScaleMode;import flash.display.Bitmap;public class ShowPic extends MovieClip{//这里我用嵌入的方式直接将图片嵌入到Flash中,图方便
//source是路径,变量为类类型
[Embed(source = "computer.png")]
private var Picture:Class;
//显示图像的对象
private var pic:Bitmap;
public function ShowPic()
{init();}private function init():void{//将舞台左上对齐,不缩放
stage.align = StageAlign.TOP_LEFT;stage.scaleMode = StageScaleMode.NO_SCALE;//这个是给C#传值,可以没有
ExternalInterface.call("toNet");
//这个是关键:获取C#传递过来的值
ExternalInterface.addCallback("sendMsg",sendMsg);
}//处理C#传递过来的值 参数个数和下面的C#传递的值的个数必须一致,不然C#会报错
private function sendMsg(s1:String,s2:String,s3:String):void{//查看舞台上面是否有对象,如果有,就清除
while (this.numChildren>0){this.removeChildAt(0);
}//这里我没有做什么优化,随便坐的一个程序
//这个对象是数据库中的记录条数
var index:int = int(s1);//这个是C#窗体的宽和高
var strArr:Array = s2.split(",");
var w = strArr[0];var h = strArr[1];//每个图像需要显示的大小
var mean:Number = w / index;//这个数据里面存储的是传递过来的数据,这里传回来的是姓名
var nameArr:Array = s3.split(",");
//新建图片对象并设置相关属性
pic=new Picture();
pic.x = stage.stageWidth / 2 - pic.width / 2;pic.y = stage.stageHeight - pic.height;//将图片添加到舞台上面
addChild(pic);//动态文本,显示需要显示在舞台上面的数据,这里显示的IP
var textField:TextField=new TextField();
textField.x = pic.x + 20;textField.y = pic.y + 20;textField.textColor = 0xffffff;textField.autoSize = TextFieldAutoSize.CENTER;textField.text = "127.0.0.1";
//添加到舞台上
addChild(textField);graphics.clear();//画线,设置样式
graphics.lineStyle(1,0,1);//循环:每循环一次,个数减1
while (index>0)
{index--;//新建图片对象,设置属性并显示
var pic1:Bitmap=new Picture();
//这个是让图片均匀分布,好看一点
pic1.x = mean * index;pic1.y = 70;pic1.width = mean - 20;pic1.height = mean - 23;addChild(pic1);//动态文本,显示需要显示在舞台上面的数据,这里显示的传回来的姓名