《Swf文件的那些事》—as函数跨平台的交互详解

SWF文件交互详解
本文深入探讨了SWF文件的交互使用方式,包括在不同环境下(如HTML、C++、Python)如何通过AS函数调用实现与SWF文件的交互。文章提供了详尽的代码示例,介绍了使用swfobject.js、Flashsatay等方法进行交互,并讲解了C++和Python环境下SWF文件的嵌入与调用技巧。

as函数调用交互

随着2020年的到来,flash也逐渐不被各大平台所使用,今天就来讲讲swf文件的交互使用方式

这篇文章纯属技术探讨,请勿用于非法用途。转载请说明来处

写在前面

先说说我为什么会写这篇文章吧。

  • 对自己来说是一种总结说明文。
  • 前几年学习flash的时候,网上也有很多交互文章,大部分呢只有简约的内容,或者源代码只是截取了一部分,没有完整的开源文件以及例子可供学习,导致很多坑需要自己填。我会将本篇文章内的源代码放入github里供大家学习参考。
  • 如果对您有帮助,可以收藏一下。之后的文章也会陆续详细的写下去。内容可能写的不好,希望各位看官可以给予您宝贵的意见。
    swf交互的思维导图

swf文件的编写

swf文件的编写工具

  • flex
  • Adobe Flash Professional CC (也叫flashcc 15年以后改名为Animate CC 在支持Flash SWF文件的基础上,加入了对HTML5的支持.)
  • other

由于这篇文章主要讲的是交互,具体各位看官使用什么软件就看你们的了。软件的下载方式呢,自行百度吧或者我之后再出个下载链接吧

回归正题,如果要进行交互使用swf 以及调用swf的代码,就要先有个swf文件
在AS代码里开通一个外部接口的调用,如思维导图所示
flash里有个类叫做ExternalInterface 就可以让你的swf文件像dll一样进行内部函数的调用
adobe官方也有详细说明和例子
ExternalInterface - AS3
简单的说需要import flash.external.ExternalInterface;
然后再ExternalInterface.addCallback(“test”,this.test);
就完成了
具体代码如下

package
{
   import flash.display.MovieClip;
   import flash.external.ExternalInterface;
   import flash.text.TextField;  
   public dynamic class Main extends MovieClip
   {
      public var val1:TextField;  
      public var val2:TextField;
      
      public var val3:TextField;
      
      public function Main()
      {
         super();
         ExternalInterface.addCallback("test",this.test);
      }
      
      public function test(param1:String = "", param2:String = "") : String
      {
         this.val1.text = String(param1);
         this.val2.text = String(param2);
         this.val3.text = String(int(param1) + int(param2));
         return this.val3.text;
      }
   }
}

编译好以后就有了一个swf文件啦。
swf文件
完成编写后就可以进行嵌入交互工作了。

Html嵌入、交互方法

1.使用swfobject.js来交互

特点:灵活多变,也是常用的调用swf方式
开源项目链接:swfobject
使用方法
首先需要建立一个容器来存放flash文件 我在这里命名为flashContent

<div id="flashContent" style="width:50%;height:50%;text-align:center;">
<a href="http://www.adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a>
</div>
<script src="js/swfobject.js"></script>
<dir>
        <input type="text" id="a" value="1">
        +
        <input type="text" id="b" value="2">
        <input type="button" name="sub" value="=" onclick="add()">
        <input type="button" name="sub" value="a=" onclick="ASadd()">
        <input type="text" id="result" value="" >
    </dir>
    //var flashUrl = "first_loading.swf";
    var flashUrl = "test.swf";
    var so = new SWFObject(flashUrl, "test", "50%", "50%", "15.0.0","#F2cFf2");
    //SWFObject参数分别为 flash的地址,flash的id,高度,宽度,版本,背景色
    so.addParam("menu", "false");
    //菜单 关闭
    so.addParam("wmode", "direct");
    //专为flashplayer10及以更高版本新增的参数,绕过浏览器进行渲染,相当于在独立的flashplayer中进行渲染。
    so.addParam("allowFullScreen", "true");
    //开启全屏
    so.addParam("allowScriptAccess", "always");
    //脚本调用权限 always代表任何flash都被允许调用脚本
    so.addParam("allowFullScreenInteractive", "true");
    //仅当在响应鼠标事件或键盘事件时,才能调用启动全屏交互模式的 actionscript。
    so.addParam("quality", "high");
    //画质 高
    so.write("flashContent");
    //加载swf文件写入到flashContent里
    var a ;
    var b ;
    //JS函数加法
    function add(){
        a= document.getElementById("a").value
        b= document.getElementById("b").value
        var result = parseInt(a) + parseInt(b);
        document.getElementById("result").value = result;
            
        }
    //调用swf里的函数
    function ASadd(){
        a= document.getElementById("a").value
        b= document.getElementById("b").value
        var result = thisMovie("test").test(a,b);//so.swfadd(a,b)
        document.getElementById("result").value = "AS_result:"+result;
    }
    //搭建js与flash互通的环境
    function thisMovie(movieName) {
        if (navigator.appName.indexOf("Microsoft") != -1) {
         return window[movieName];
        } else {
         return document[movieName];
        }
    }

运行效果
IE浏览器运行效果
在IE上运行的结果

2.单一object嵌入、调用方式

这种方法的名字叫做 Flash satay,最早是2002年由 Drew McLellan 发表在 A List Apart 上,后来又经过了几次完善:

<object id="test"  name="test" 
  type="application/x-shockwave-flash" data="test.swf" width="550" height="400">
    <param name="movie" value="test.swf"/>
    <param name="quality" value="high"/>
    <param name="allowscriptaccess" value="always"/>
    <a href="http://www.adobe.com/go/getflash">
        <img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player"/>
    </a>
  </object>
  <form name="form1" onsubmit="return false;">
         <input type="text" id="a" value="1" />
		 <input type="text" id="b" value="2" />
         <input type="button" value="Send" onclick="sendToActionScript();" /><br />
         <textarea cols="60" rows="20" name="output" readonly="true">Initializing...</textarea>
     </form>
var jsReady = false;
     function isReady() {
         return jsReady;
     }
	 var a;
	 var b;
     function pageInit() {
         jsReady = true;
         document.forms["form1"].output.value += "\n" + "JavaScript is ready.\n";
     }
     function sendToActionScript() {
		 a = document.getElementById("a").value
		 b = document.getElementById("b").value
       document.forms["form1"].output.value += "AS_result: "+a+"+"+b+"="+document.getElementById("flashContent").test(a,b)+"\n";
     }

这个也是adobe官方例子中提供的方法

运行结果
IE运行结果

3.双object加载、交互

<object id="exercises" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="214" height="144">
    <param name="movie" value="test.swf" />
    <param name="wmode" value="window" />
    <param name="flashvars" value=""/>
    <!--[if !IE]><!-->
    <object id="exercisesEx" type="application/x-shockwave-flash"
        data="test.swf" width="214" height="144">
        <param name="flashvars" value=""/>
    <!--<![endif]-->
        <!--[if !IE]><!-->
        <!--<![endif]-->
        <a href="http://www.adobe.com/go/getflashplayer">
            <img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" />
        </a>
    <!--[if !IE]><!-->
    </object>
    <!--<![endif]-->
</object>

4.flex提供的标准方法

HTML代码(这些代码都是flex builder自动生成的,用于将flash嵌入到网页里。)
修改后加入调用方式,基本一样。

  • as使用ExternalInterface.addCallback注册回调函数
  • 在js函数中根据flash在网页中的id获取实例
  • 用上面获取到flash实例,调用as的函数
<noscript>
    <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
            id="test" width="100%" height="100%"
            codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
            <param name="movie" value="test.swf" />
            <param name="quality" value="high" />
            <param name="bgcolor" value="#869ca7" />
            <param name="allowScriptAccess" value="sameDomain" />
            <embed src="test.swf" quality="high" bgcolor="#869ca7"
                width="100%" height="100%" name="test" align="middle"
                play="true"
                loop="false"
                quality="high"
                allowScriptAccess="sameDomain"
                type="application/x-shockwave-flash"
                pluginspage="http://www.adobe.com/go/getflashplayer">
            </embed>
    </object>
</noscript>
<form name="form1" onsubmit="return false;">
         <input type="text" id="a" value="1" />
         <input type="text" id="b" value="2" />
         <input type="button" value="Send" onclick="sendToActionScript()" /><br />
         <textarea cols="60" rows="20" name="output" readonly="true">Initializing...</textarea>
</form>
    var a ;
	var b ;
function sendToActionScript() {
     a = document.getElementById("a").value
     b = document.getElementById("b").value
     //根据id获取flash实例,在这里id是test,可以从Embed
     var flash = (navigator.appName.indexOf ("Microsoft") !=-1)?window["test"]:document["test"];
     //调用ActionScript注册的回调方法
    document.forms["form1"].output.value +="\n"+ "AS_result: "+a+"+"+b+"="+flash.test(a,b);
}
<!--
// -----------------------------------------------------------------------------
// Globals
// Major version of Flash required
var requiredMajorVersion = 9;
// Minor version of Flash required
var requiredMinorVersion = 0;
// Minor version of Flash required
var requiredRevision = 60;
// -----------------------------------------------------------------------------
// -->
<!--
// Version check for the Flash Player that has the ability to start Player Product Install (6.0r65)
var hasProductInstall = DetectFlashVer(6, 0, 65);

// Version check based upon the values defined in globals
var hasRequestedVersion = DetectFlashVer(requiredMajorVersion, requiredMinorVersion, requiredRevision);

if ( hasProductInstall && !hasRequestedVersion ) {
    // DO NOT MODIFY THE FOLLOWING FOUR LINES
// Location visited after installation is complete if installation is required
var MMPlayerType = (isIE == true) ? "ActiveX" : "PlugIn";
    var MMredirectURL = window.location;
    document.title = document.title.slice(0, 47) + " - Flash Player Installation";
    var MMdoctitle = document.title;

    AC_FL_RunContent(
        "src", "playerProductInstall",
        "FlashVars", "MMredirectURL="+MMredirectURL+'&MMplayerType='+MMPlayerType+'&MMdoctitle='+MMdoctitle+"",
        "width", "100%",
        "height", "100%",
        "align", "middle",
        "id", "test",
        "quality", "high",
        "bgcolor", "#869ca7",
        "name", "test",
        "allowScriptAccess","sameDomain",
        "type", "application/x-shockwave-flash",
        "pluginspage", "http://www.adobe.com/go/getflashplayer"
    );
} else if (hasRequestedVersion) {
    // if we've detected an acceptable version
// embed the Flash Content SWF when all tests are passed
    AC_FL_RunContent(
            "src", "test",
            "width", "100%",
            "height", "100%",
            "align", "middle",
            "id", "test",
            "quality", "high",
            "bgcolor", "#869ca7",
            "name", "test",
            "allowScriptAccess","sameDomain",
            "type", "application/x-shockwave-flash",
            "pluginspage", "http://www.adobe.com/go/getflashplayer"
    );
} else { // flash is too old or we can't detect the plugin
var alternateContent = 'Alternate HTML content should be placed here. '
    + 'This content requires the Adobe Flash Player. '
       + '<a href=http://www.adobe.com/go/getflash/>Get Flash</a>';
    document.write(alternateContent); // insert non-flash content
}

运行结果
IE运行结果图:Flex

C++嵌入、交互方法

在官方给出的使用 ExternalInterface 类
其中外部 API 的 XML 格式

  • ActionScript 与承载 Shockwave Flash ActiveX 控件的应用程序间的通信使用特定的 XML 格式对函数调用和值进行编码。
    外部 API 使用的 XML 格式分为两种。
    1. 一种格式用于表示函数调用。
    1. 另一种格式用于表示各个值;
  • 此格式用于函数中的参数及函数返回值。函数调用的 XML 格式用于对 ActionScript 的调用和来自 ActionScript 的调用。对于来自 ActionScript 的函数调用,Flash Player 将 XML 传递给容器;而对于来自容器的调用,Flash Player 需要容器应用程序将向其传递一个此格式的 XML 字符串。下面的 XML 片断说明了一个 XML 格式的函数调用示例:
<invoke name="functionName" returntype="xml"> 
    <arguments> 
        ... (individual argument values) 
    </arguments> 
</invoke>
节点名属性说明
invokename指示要调用的函数的名称
invokereturntype总是为 xml
arguments该节点的子节点是使用单个值格式

arguments 子节点,格式设置的参数值。每个值(包括函数参数和函数返回值)均使用一个格式设置方案,除了实际值之外,该方案还包括数据类型信息。

ActionScript 类/值C# 类/值格式注释
nullnull<null/>
Boolean truebool true<true/>
Boolean falsefalse<false/>
Stringstring<string>字符串值</string>
Number、int、uintsingle、double、int、uint<number>27.5</number> <number>-12</number>
Array(元素可以是混合类型)允许混合类型元素的集合,如 ArrayList 或 object[]Arrayproperty 节点定义各个元素,而 id 属性为从零开始的数值索引。
Object含有字符串键和对象值的字典,如具有字符串键的 HashTableObjectproperty 节点定义各个属性,而 id 属性为属性名称(字符串)。
其他内置或自定义的类<null/> or <object></object>ActionScript 将其他对象编码为 null 或空对象。不管是哪种情况,所有属性值都会丢失。

重点来了!!敲黑板~

外部 API 可用来与支持 ActiveX 控件的任何编程语言或运行时进行通信,而不仅限于 C# 应用程序。

我们可以使用 F_IN_BOX

F-IN-BOX is a developer’s library to enhance Adobe Flash Player
ActiveX features. It does not use its own engine to display movies but
provide a wrapper around official swflash.ocx/flash.ocx code instead.
Thus it is possible to avoid certain Adobe Flash Player ActiveX
limitations.

Both 32-bit and 64-bit versions of Flash ActiveX are supported.

There are Delphi Edition (for Delphi, Builder C++, RAD Studio), .Net
Edition (for C#, VB.Net and other .Net languages) and DLL Edition (for
C++, VB6 and other languages that support dll).

译文

什么是F-IN-BOX?
F-IN-BOX是开发人员的库,用于增强Adobe Flash Player ActiveX功能。
它不使用自己的引擎来显示电影,而是提供围绕官方swflash.ocx / flash.ocx代码的包装。 因此可以避免某些Adobe
Flash Player ActiveX限制。
支持Flash ActiveX的32位和64位版本。
有Delphi Edition(用于Delphi,Builder C ++,RAD Studio)、. Net
Edition(用于C#,VB.Net和其他.Net语言)和DLL Edition(用于C ++,VB6和其他支持dll的语言)。

这是一款商业组件,网上也有很多破解版不过都是付费下载,我这有一个F-IN-BOX 4.5版,将会放在我的github里

// FInBox.cpp
// 本示例修改涉及 FInBox.h FInBox.cpp
 
#include "stdafx.h"
#include "FInBox.h"
 
#define MAX_LOADSTRING 100
 
// 全局变量:
HINSTANCE hInst;								// 当前实例
TCHAR szTitle[MAX_LOADSTRING];					// 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING];			// 主窗口类名
 
//=================================================
//=================MY-ADD-BEG======================
 
HFPC g_hFPC = NULL;
HWND swfWnd = NULL;
 
//=================MY-ADD-END======================
//=================================================
 
// 此代码模块中包含的函数的前向声明:
ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK	About(HWND, UINT, WPARAM, LPARAM);
 
int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);
 
 	// TODO: 在此放置代码。
	MSG msg;
	HACCEL hAccelTable;
 
	// 初始化全局字符串
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_FINBOX, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);
 
	// 执行应用程序初始化:
	if (!InitInstance (hInstance, nCmdShow))
	{
		return FALSE;
	}
 
	hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_FINBOX));
 
	// 主消息循环:
	while (GetMessage(&msg, NULL, 0, 0))
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
 
	return (int) msg.wParam;
}
 
 
 
//
//  函数: MyRegisterClass()
//
//  目的: 注册窗口类。
//
//  注释:
//
//    仅当希望
//    此代码与添加到 Windows 95 中的“RegisterClassEx”
//    函数之前的 Win32 系统兼容时,才需要此函数及其用法。调用此函数十分重要,
//    这样应用程序就可以获得关联的
//    “格式正确的”小图标。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;
 
	wcex.cbSize = sizeof(WNDCLASSEX);
 
	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_FINBOX));
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+2);
	wcex.lpszMenuName	= MAKEINTRESOURCE(IDC_FINBOX);
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
 
	return RegisterClassEx(&wcex);
}
 
//
//   函数: InitInstance(HINSTANCE, int)
//
//   目的: 保存实例句柄并创建主窗口
//
//   注释:
//
//        在此函数中,我们在全局变量中保存实例句柄并
//        创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;
 
   hInst = hInstance; // 将实例句柄存储在全局变量中
 
   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, 400, 300, NULL, NULL, hInstance, NULL);
 
   if (!hWnd)
   {
      return FALSE;
   }
 
   //=================================================
   //=================MY-ADD-BEG======================
 
   g_hFPC = FPC_LoadRegisteredOCX();
   if (NULL == g_hFPC)
   {
	   ::MessageBox(NULL, _T("flash OCX have existed"), 0, 0);
	   return 0;
   }
   else
   {
	   //::MessageBox(NULL, _T("flash OCX no existed"), 0, 0);
   }
   //
   RECT rc = {0, 0, 200, 200};
   swfWnd = CreateWindow((LPCTSTR)FPC_GetClassAtom(g_hFPC), NULL,
	   WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
	   rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
	   hWnd, NULL, NULL, NULL);
   if (NULL == swfWnd)
   {
	   return FALSE;
   }
   //
   SFPCPutMovie FPCPutMovie;
   SFPCPutStandardMenu FPCPutStandardMenu;
 
   char exePath[MAX_PATH];
   GetCurrentDirectory(MAX_PATH, exePath);
   std::string absSwfPath(exePath);
   absSwfPath += "/movie.swf";
   FPCPutMovie.lpszBuffer = absSwfPath.c_str();//TEXT("D:\\movie.swf");
   ::SendMessage(swfWnd, FPCM_PUT_MOVIE, 0, (LPARAM)&FPCPutMovie);
 
   FPC_Play(swfWnd);
 
   FPCPutStandardMenu.StandardMenu = TRUE;
   ::SendMessage(swfWnd, FPCM_PUT_STANDARD_MENU, 0, (LPARAM)&FPCPutStandardMenu);
   
   //=================MY-ADD-END======================
   //=================================================
 
   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);
 
   return TRUE;
}
 
//
//  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的: 处理主窗口的消息。
//
//  WM_COMMAND	- 处理应用程序菜单
//  WM_PAINT	- 绘制主窗口
//  WM_DESTROY	- 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;
 
	switch (message)
	{
	case WM_COMMAND:
		wmId    = LOWORD(wParam);
		wmEvent = HIWORD(wParam);
		// 分析菜单选择:
		switch (wmId)
		{
		case IDM_ABOUT:
			DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
			break;
		case IDM_EXIT:
			DestroyWindow(hWnd);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
		break;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		// TODO: 在此添加任意绘图代码...
		EndPaint(hWnd, &ps);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}
 
// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);
	switch (message)
	{
	case WM_INITDIALOG:
		return (INT_PTR)TRUE;
 
	case WM_COMMAND:
		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
		{
			EndDialog(hDlg, LOWORD(wParam));
			return (INT_PTR)TRUE;
		}
		break;
	}
	return (INT_PTR)FALSE;
}

python嵌入、交互方法

wxPython是一套基于Python的第三方GUI插件,可用Python制作丰富的图形化界面程序。

安装:pip install wxPython
网站下载安装 https://pypi.org/project/wxPython/#files
demo和docs下载:https://extras.wxpython.org/wxPython4/extras/

# -*- coding: utf-8 -*-
import wx
import os
from xml.dom import minidom
from wx.lib.flashwin import FlashWindow

class EIDataSerializer:
    __xmlData=None
    def __packNumber(self,p,x):
        p.appendChild(self.__xmlData.createElement('number')).appendChild(self.__xmlData.createTextNode(str(x)))
        return
    def __packString(self,p,x):
        p.appendChild(self.__xmlData.createElement('string')).appendChild(self.__xmlData.createTextNode(x))
        return
    def __packNone(self,p):
        p.appendChild(self.__xmlData.createElement('null'))
        return
    def __packBool(self,p,x):
        if x:
            p.appendChild(self.__xmlData.createElement('true'))
        else:
            p.appendChild(self.__xmlData.createElement('false'))
        return
    def __packDict(self,p,x):
        p=p.appendChild(self.__xmlData.createElement('object'))
        for k,v in x.items():
            n=p.appendChild(self.__xmlData.createElement('property'))
            n.setAttribute('id',str(k))
            self.__packData(n,v)
        return
    def __packList(self,p,x):
        p=p.appendChild(self.__xmlData.createElement('array'))
        i=0
        for v in x:
            n=p.appendChild(self.__xmlData.createElement('property'))
            n.setAttribute('id',str(i))
            self.__packData(n,v)
            i+=1
        return
    def __packData(self,p,x): ##将Python的类型打包成XML
        t=type(x)
        if t in (int,long,float):               
            self.__packNumber(p,x)
        elif t in (str,unicode):                
            self.__packString(p,x)
        elif x==None:                           
            self.__packNone(p)
        elif t==bool:       
            self.__packBool(p,x)
        elif t in (list,tuple):
            self.__packList(p,x)
        elif t==dict:
            self.__packDict(p,x)
        return
    def __unpackNumber(self,p):
        try:
            return int(p.firstChild.nodeValue)
        except ValueError:
            try:
                return float(p.firstChild.nodeValue)
            except ValueError:
                return None
    def __unpackString(self,p):
        return p.firstChild.nodeValue
    def __unpackTrue(self):
        return True
    def __unpackFalse(self):
        return False
    def __unpackNull(self):
        return None
    def __unpackUndefined(self):
        return None
    def __unpackObject(self,p):
        d={}
        for n in p.childNodes:
            d[n.getAttribute('id')]=self.__unpackData(n.firstChild)
        return d
    def __unpackArray(self,p):
        a=[]
        for n in p.childNodes:
            a.append(self.__unpackData(n.firstChild))
        return a
    def __unpackData(self,p): ##将Flash传过来的XML解析成Python类型数值
        t=p.nodeName
        if t=='number':
            return self.__unpackNumber(p)
        elif t=='string':
            return self.__unpackString(p)
        elif t=='true':
            return self.__unpackTrue()
        elif t=='false':
            return self.__unpackFalse()
        elif t=='null':
            return self.__unpackNull()
        elif t=='undefined':
            return self.__unpackUndefined()
        elif t=='object':
            return self.__unpackObject(p)
        elif t=='array':
            return self.__unpackArray(p)
    def serializeReturn(self,v):
        self.__xmlData=minidom.Document()
        p=self.__xmlData
        self.__packData(p,v)
        return self.__xmlData.toxml()
    def serializeCall(self,name,args):
        self.__xmlData=minidom.Document()
        p=self.__xmlData.appendChild(self.__xmlData.createElement('invoke'))
        p.setAttribute('name',name)
        p.setAttribute('returntype','xml')
        p=p.appendChild(self.__xmlData.createElement('arguments'))
        for v in args:
            self.__packData(p,v)
        s=self.__xmlData.documentElement.toxml()
        return s
    def deserializeReturn(self,s):
        self.__xmlData=minidom.parseString(s)
        p=self.__xmlData.documentElement
        return self.__unpackData(p)
    def deserializeCall(self,s):
        self.__xmlData=minidom.parseString(s)
        p=self.__xmlData.documentElement#invoke
        name=p.getAttribute('name')
        args=[]
        p=p.firstChild#arguments
        for n in p.childNodes:
            args.append(self.__unpackData(n))
        return (name,args)

class FlashFrame(wx.Frame):
    def __init__(self, parent, fid, title): 
        wx.Frame.__init__(self, parent, fid, title)  
        sort = -1
        self.rootPanel = wx.Panel(self, sort)
        self.flashWin  = FlashWindow(self.rootPanel)
        self.txtBox    = wx.TextCtrl(self.rootPanel, wx.NewId())
        self.btSend    = wx.Button(self.rootPanel, wx.NewId(), "Call Flash")
    
        self.flashSizer = wx.BoxSizer(wx.VERTICAL)
        self.flashSizer.Add(self.flashWin, proportion=1,   flag=wx.EXPAND)
        self.flashSizer.Add(self.txtBox,   proportion=0.3, flag=wx.EXPAND|wx.ALL, border=2)
        self.flashSizer.Add(self.btSend,   proportion=0.3, flag=wx.EXPAND|wx.ALL, border=2)
        self.rootPanel.SetSizer(self.flashSizer)
        self.rootPanel.SetAutoLayout(True)

        self.flashWin.AddEventSink(self)
        self.rootPanel.Bind(wx.EVT_BUTTON, self.sendToFlashHandler, self.btSend)
        self.flashWin.LoadMovie(0, os.getcwd() + os.path.sep + 'test.swf')
        return

    def FlashCall(self, xmlStr):
        serializer = EIDataSerializer()
        xmlStr   = xmlStr.encode('utf-8')             ##从Flash控件消息接收的XML字符串
        print "FlashCall: \n" + xmlStr
        name, args       = serializer.deserializeCall(xmlStr) ##解析成Python函数名和参数
        print name
        print args
        print args[0]
        result = "Python返回: " + args[0]
        result = serializer.serializeReturn(result)                     ##返回值打包成XML  
        self.flashWin.ctrl.SetReturnValue(result)
    


    def sendToFlashHandler(self, btEvent):
        sendStr = self.txtBox.GetValue()
        flashFunctionName = "helloFlash"
        xmlStr = "<invoke name=\"" + flashFunctionName + "\" returntype=\"xml\">"
        xmlStr += "<arguments>"
        xmlStr += "<string>" + sendStr + "</string>"
        xmlStr += "</arguments>"
        xmlStr += "</invoke>"
        rValue = self.flashWin.ctrl.CallFunction(xmlStr)
        print "Flash返回: ", rValue


app = wx.PySimpleApp()
frame = FlashFrame(None, -1, "Python & Flash")
frame.Show(True)
app.MainLoop()
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值