c# 与flash通信简介
许久不曾写随笔,即使许久的怠惰,是该抬抬头,看看天了。
公司项目,项目要求是在winForm端先获取下位机的肌电信号采集数据,然后根据这些数据的变化来控制flash游戏,这样一些患者在flash游戏中达到肢体训练的效果。
在这里 需要用到c#与flash的通信, 先上通信示例
ActionScript3.0 与ActionScript2.0 略有差异,但和C#的通信方式是不变的。
function xmlToArray(list:XML):Array {
//xml转数组
list.ignoreWhite = true;
var ar:Array = new Array();
var list_node:XMLNode = list.firstChild.childNodes[];
var l:Number = list_node.childNodes.length;
for (var i:Number = ; i<l; i++) {
var node:XMLNode = list_node.childNodes[i];
var ob = new Array();
ob.push(node.childNodes[].childNodes[].nodeValue);
ob.push(node.childNodes[].childNodes[].nodeValue);
ar.push(ob);
}
return ar;
}
ExternalInterface.addCallback("onPlatformMessage",null,onPlatformMessage);
var xmlContent:XML;
var messageName:String, messageType:String, gameId:String;
function onPlatformMessage(args:String) {
xmlContent = new XML(args);
list_arr = xmlToArray(xmlContent);
//fscommand('Message', '<Message name="GAME_SCORE_REPLY" type="2" gameId="4025"><PlayerScore>'+list_arr+'</PlayerScore></Message>');
messageName = xmlContent.firstChild.attributes.name;
messageType = xmlContent.firstChild.attributes.type;
gameId = xmlContent.firstChild.attributes.gameId;
if (messageType == '' && gameId == '') {
switch (messageName) {
case 'GAME_VERSION' :
fscommand('Message', '<Message name="GAME_VERSION_REPLY" type="2" gameId="4025"><GameVersion>1.0</GameVersion></Message>');
break;
case 'PLAYER_ENTER' :
if (gameFinished) {
playerMode = xmlContent.childNodes[].childNodes[].childNodes[].nodeValue;
if (playerMode != ) {
//playerMode=xmlContent.PlayerMode;
playerName = xmlContent.childNodes[].childNodes[].childNodes[].childNodes[].nodeValue;
level = xmlContent.childNodes[].childNodes[].childNodes[].nodeValue;
score = xmlContent.childNodes[].childNodes[].childNodes[].childNodes[].nodeValue;
if(level>)(level=);
gotoAndStop();
fscommand('Message', '<Message name="GAME_ENTER_OK" type="2" gameId="4025"></Message>');
}
}
break;
case 'GAME_PAUSE' :
if (!gameFinished) {
pauseGame(true);
}
break;
case 'GAME_RESUME' :
if (!gameFinished) {
continueGame();
}
break;
case 'GAME_LEAVE' :
gameFinished = true;
fscommand('Message', '<Message name="GAME_LEAVE_OK" type="2" gameId="4025"><PlayerScore>'+score+'</PlayerScore><GameStage>'+level+'</GameStage></Message>');
break;
case 'GAME_HELP' :
break;
case 'GAME_SOUND' :
break;
case 'GET_GAME_SCORE' :
fscommand('Message', '<Message name="GAME_SCORE_REPLY" type="2" gameId="4025"><PlayerScore>'+score+'</PlayerScore></Message>');
break;
case 'GET_GAME_STAGE' :
fscommand('Message', '<Message name="GAME_STAGE_REPLY" type="2" gameId="4025"><GameStage>'+level+'</GameStage></Message>');
break;
case 'SET_GAME_STAGE' :
if (!gameFinished) {
level = xmlContent.childNodes[].childNodes[].childNodes[].nodeValue;
gotoAndPlay();
fscommand('Message', '<Message name="SET_GAME_STAGE_OK" type="2" gameId="4025"></Message>');
}
break;
case 'GET_GAME_STATUS' :
//tmpInt = xmlContent.firstChild.attributes.GameStage;
fscommand('Message', '<Message name="GAME_STATUS_REPLY" type="2" gameId="4025"><GameStatus>'+gameStatus+'</GameStatus></Message>');
break;
case 'SET_LANGUAGE' :
var language = xmlContent.firstChild.attributes.GameLanguage;
break;
default :
searchHighscore();
}
}
//end if
}
//end onPlatformMessage
Flash端的ActionScript2.0代码
如上示例:
Flash接收c#消息方式:
ExternalInterface.addCallback("onPlatformMessage",null,onPlatformMessage);
引号中的onPlatformMessage是flash用于接收c#消息的方法名
后面的onPlatformMessage 是接收到的c#传递的参数,该参数可以有一个或多个(本项目中只用到一个参数)。
然后再onPlatformMessage方法中,AS(ActionScript)会先把c#传递过来的额XML的字符串进行解析,解析之后就可以执行flash的相应动作。
Flash回复c#消息
fscommand('Message', '<Message name="SET_GAME_STAGE_OK" type="2" gameId="4025"></Message>');
C#端的操作
C#端使用的是WinForm形式。
准备工作:
首先添加对 COM 组件 Shockwave Flash Object 的引用,将该组件拖到窗体上之后,可以设置如下关键属性:
Movie: Flash 的存放地址
EmbedMovie: 是否嵌入到程序的资源中。
或者在程序中把flash加载进去:
player.LoadMovie(0, Application.StartupPath + "\\EITest.swf");
// player.Play();
在使用player.Play()中遇到的问题是:
在c#与ActionScript2.0 通信中在Load使用使用Play() 命令可以使用flash正常播放,但在c#与ActionScript3.0 的通信中却遇到了错误。后来查找原因大概是在执行 player.LoadMovie() 的时候是把flash加载进来,player.Play() 会自动播放flash,相当于在ActionScript语法中执行了play方法,这样会与flash中原来的方法造成冲突,最后是没有使用后一步的player.Play()方法。
C# 接收flash的消息:
private void player_FSCommand(object sender, AxShockwaveFlashObjects._IShockwaveFlashEvents_FSCommandEvent e)
{
if (e.command == "Message")
{
lblreceive.Text = e.args;
//游戏载入时,发送参与人的编号和姓名
if (e.args.IndexOf("GAME_LOAD_OK") != -)
{
messageName = "PLAYER_LOAD";
LoadPlayer();
}
}
}
c#接收flash消息
上面的player是与flash通信的客户端的ID,在winForm中注册player的FSCommand的方法,此方法的作用即时在主线程中不停地刷新来接收flash发送给c#的消息。
其中e.command 是flash中 fscommand函数的第一个参数
e.args是flash中 fscommand函数的第二个参数
c#发送给flash的消息
private void Command_SetSpeed(int speed)
{
messageName = "Action_Speed";
player.CallFunction("<invoke name=\"onPlatformMessage\" returntype=\"xml\"><arguments><string>" +
" <Message name=\"" + messageName + "\" type=\"1\" gameId=\"" + gameId + "\"><Speed>" + speed.ToString() + "</Speed></Message>" +
"</string></arguments></invoke>");
}
c#接收flash消息
在c#中使用player.CallFunction()方法向flash发送消息,其中"onPlatformMessage"是flash接收消息的方法名。
在本项目中,向flash发送的消息,只有<string>标签中的消息不用,其他的格式都是通用的。
通信原理及过程:
通信原理个人不甚懂,摘抄他人的解释共享。
其基本过程为:flash中注册函数——将要调用的函数名、参数等信息打包为xml—>将xml传递到flash中执行调用—>执行ActionScript函数—>flash自动将结果打包为xml—>将结果xml传递回C# —>C#解析xml得到返回值
可见,flash与C#通信是通过特定格式的xml文件进行的,因此为了实现通信,C#必须实现一下功能:识别该xml格式以得到flash发送来的信心,将需要传送给flash的信息打包成flash能识别的xml格式。为了使用方便我们可以设计一个代理类专门负责数据的解析与打包工作,这样我们就可以透明的使用该代理类来实现flash与C#间的互相调用。
在flash的示例中有一个IntrovertIM_CSharp项目较好的实现了代理的编写,一般情况下,使用该示例中的ExternalInterfaceProxy类足以满足要求,因此方便起见我也直接采用了该代理类。
该类的使用非常简单,通过将flash控件作为参数传递给该类的构造函数,我们就可以建立一个给控件的代理,简单的响应代理的ExternalInterfaceCall事件及使用代理类的Call()方法就能实现与flash通信,中间的数据转换工作完全由代理透明的实现,用户无需关心。
其它语言及程序课根据上面原理编写自己的代理类来实现数据的解析与打包工作。
c# 与flash通信简介的更多相关文章
- Javascript与Flash通信全解析
原文:https://www.imququ.com/post/39.html Flash已经提供了ExternalInterface接口与JavaScript通信,ExternalInterface有 ...
- Flash Memory 简介【转】
本文转载自:https://linux.codingbelief.com/zh/storage/emmc/ Flash Memory 是一种非易失性的存储器.在嵌入式系统中通常用于存放系统.应用和数据 ...
- socket通信简介
转:http://blog.csdn.net/xiaoweige207/article/details/6211577 “一切皆Socket!” 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的 ...
- NAND Flash内部结构简介
介绍 1965年,在双极管被W.Shockley.W.Brattain和J.Bardeen三人发明出来之后,Intel的合作创始人Gordon Moore发现了这样一条法则:当价格不变时,集成 ...
- 转:socket通信简介
转:http://blog.csdn.net/xiaoweige207/article/details/6211577/ 我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览器浏览网页 ...
- dubbo结构及通信简介
一.导论 dubbo作为阿里开发优秀的rpc服务框架,现已广泛用于各大rpc项目之间的远程通信,虽然阿里现在已经没有维护dubbo的开发,但是其结构设计也是值得学习. 二.结构简介 这部分只是简单介绍 ...
- ROM、PROM、EPROM、EEPROM、FLASH ROM简介
ROM指的是"只读存储器",即Read-Only Memory.这是一种线路最简单半导体电路,通过掩模工艺, 一次性制造,其中的代码与数据将永久保存(除非坏掉),不能进行修改.这玩 ...
- [转]UART通信简介
1.前言 UART通信,即通用异步收发传输器(Universal Asynchronous Receiver/Transmitter). 串行通信是指利用一条传输线将资料一位位地顺序传送.特点是通信线 ...
- 【转】socket 通信简介
转自:http://blog.csdn.net/xiaoweige207/article/details/6211577/ “一切皆Socket!” 话虽些许夸张,但是事实也是,现在的网络编程几乎都是 ...
随机推荐
- CF 191 总结
A. Flipping Game 链接:http://codeforces.com/contest/327/problem/A 题意:从 i 到 j 翻转一次使得 1 的 个数最多~ 直接暴力搞~ # ...
- 银行卡BIN码大全
BIN号即银行标识代码的英文缩写.BIN由6位数字表示,出现在卡号的前6位,由国际标准化组织(ISO)分配给各从事跨行转接交换的银行卡组织.银行卡的卡号是标识发卡机构和持卡人信息的号码,由以下三部分组 ...
- 关于Haproxy安装和配置:负载配置【haproxy.cfg】问题记录
1. 存放地址: more /etc/haproxy/haproxy.cfg ps -ef | grep haproxy 看看有没有haproxy的进程就是了 或者看看服务器的23306的端口有没有 ...
- PHP 文件操作函数大全
<?php 读取文件夹: $handler = opendir("c:\");//打开文件夹 while($dir = readdir($handler)){//遍历文件夹 ...
- Android之完美退出方法
为什么要写这篇文章? 网上有很多种退出方法,可实际上很多方法都不通用(在某个版本下可用,到了另一个版本就不行),或者方法的实际效果根本就和其描述不符(也不知道那些发帖的人测没测试过). 但我们的需求又 ...
- Swift 中的利刃,函数和闭包
input[type="date"].form-control,.input-group-sm>input[type="date"].input-grou ...
- Matlab实现加性高斯白噪声信道(AWGN)下的digital调制格式识别分类
Matlab实现加性高斯白噪声信道(AWGN)下的digital调制格式识别分类 内容大纲 加性高斯白噪声信道(AWGN)下的digital调制格式识别分类 (1. PSK; 2. QPSK; 3.8 ...
- 使用xilinx ip core FIFO First- World First-Through (FWFT)模式的注意事项
也许很多人知道xilinx ip core 中的fifo可以配成standard 模式和FWFT模式,并知道两者的区别是:standard模式下,当rd为高时,fifo会延时一个时钟输出数据(时序逻辑 ...
- maven属性
Maven内置了三大特性:属性.Profile和资源过滤来支持构建的灵活性. 内置属性:主要有两个常用内置属性 ${basedir}表示项目根目录,即包含pom.xml文件的目录 ${version} ...
- [shell基础]——awk命令
关于awk awk是一个强大的文本分析工具,相对于grep的查找.sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大. 简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开 ...