Flex与VC++交相通信
Flex以前采用 flash.system.fscommand 与其他web container 或者 ActiveX container进行通信,但是fscommand有一些弊端,比如说//未完待续不能及时返回数据等等,而且已经过时很久了。
还是说说ExternalInterface吧,这个接口类可以让Flex程序被其他的web或者common application container调用,入JavaScript, VB, VC++程序等等,当然相反地,它也让Flex能够去调用对方的函数,并且都能够获取返回值。
直接看例子吧:
首先是Flex调用web或者application container的函数,
1. Flex调用Javascript函数,并且获取返回值:
//Flex中定义调用Javascript的方法
public function showInfoWithJavaScript() : void
{
Security.allowDomain("*"); //定义访问安全,其中参数可以是‘*’,也是可以一些domain,例如www.xxx.com,IP地址等
if (ExternalInterface.avaliable) //检测flash player是否在一个容器里面,并且提供被外部调用的借口,即Flex调用Javascript的有效性
{
var arr : Array = ExternalInterface.call("showInfo", info) // 调用Javascript的showInfo方法,并且传递参数info,这个参数可以是常量,也可以是变量,String或者是Object,然后获取Javascript返回的数据
}
else
{
Alert.show("调用外部的Javascript失败","警告");
}
}
//以下是html中加入定义了showInfo方法的javascript
/html-template/index.template.html
<head>
...
<script language="JavaScript" src="externalInterface.js"></script>
</head>
//以下是定义的externalInterface.js
<script language="javascript">
var arr : array = ['1','2','3'];
function showInfo(param) {
if (param == null)
return null;
else
return arr; //返回数据给Flex
}
</script>
2. Javascript调用Flex的函数,并且获取返回值
//Flex中定义被Javascript调用的函数
private var arr : Array = ['1','2','3'];
public function init() : void
{
if (ExternalInterface.avaliable)
{
ExternalInterface.addCallBack("callFlex", beingCalled);
}
}
public function beingCalled(param : Object) : void
{
if (param == null)
return null;
else
return arr; //返回给Javascript数据
}
//Javascript中调用Flex地方法
<script language="JavaScript">
// 其中flashObject可以通过Object的embed引入;
var callResult = flashObject.myFunction("my name");
</script>
...
<object id="flashObject"...>
...
<embed name="flashObject".../>
</object>
3. Flex调用VC++本地程序,并且获取返回值
//Flex中定义调用VC++的方法
public function callCPPlus() : void
{
if (ExternalInterface.avaliable) //检测flash player是否在一个容器里面,并且提供被外部调用的借口,即Flex调用VC++的有效性
{
var str : String = ExternalInterface.call("returnToFlex", info) // 调用CV++的showInfo方法,并且传递参数info,这个参数可以是常量,也可以是变量,String或者是Object,然后获取VC++返回的数据,这个返回的数据是XML格式的数据,其格式在后面给出;其中这个call方法让flash player触发一个Flash Call事件来调用VC++方法,其中参数也会被格式化为xml格式的数据;也即他们之间的通信是通过XML格式的数据;
}
else
{
Alert.show("调用外部的VC++方法失败","警告");
}
}
//VC++中定以被Flex调用的方法
//a. 首先需要在VC++中嵌入flash player插件,定义其对象为m_FlashPlayer
//b. VC++通过事件对象的request来获取Flex过来的数据
//c. 通过m_FlashPlayer的SetReturnValue方法返回xml格式的数据给Flex
void CMyBicapDlg::OnFlashCallShockwaveflash1(LPCTSTR request)
{
// TODO: Add your control notification handler code here
// "<invoke name='%s' returntype='xml'><arguments><string>%s</string></arguments></invoke>"
// parse request
TiXmlDocument request_xml;
request_xml.Parse(request);
const char* request_name = request_xml.RootElement()->Attribute("name");
if (strcmp(request_name,"savedVideosDirectory") == 0 || strcmp(request_name,"bufferDirectory") == 0 || strcmp(request_name,"preferredExportDirectory") == 0)
{
// choose path
CoInitialize(NULL);
BROWSEINFO bi;
bi.hwndOwner = this->GetSafeHwnd();
bi.pidlRoot = NULL;
bi.pszDisplayName = NULL;
bi.lpszTitle = NULL;
bi.ulFlags = BIF_BROWSEFORCOMPUTER|BIF_RETURNONLYFSDIRS|BIF_STATUSTEXT;
bi.lpfn = NULL;
LPCITEMIDLIST pidl = SHBrowseForFolder(&bi);
if(pidl != NULL)
{
TCHAR tpath[MAX_PATH] = _T("");
BOOL bresult = SHGetPathFromIDList(pidl, tpath);
if (bresult)
{
std::string re_value = "<string>";
re_value = re_value+tpath+"</string>";
m_FlashPlayer.SetReturnValue(re_value.c_str());
}
}
CoUninitialize();
}
}
4. VC++调用Flex定义的函数
//Flex端定义被VC++调用的方法,
private function initApp() : void
{
Security.allowDomain("*");
if (ExternalInterface.available)
{
ExternalInterface.addCallback("sendToActionScript", receivedFromCPPlus);
}
}
public function receivedFromCPPlus(value : String) : String
{
Alert.show("C++传入参数->" + value, "提示"); //receive from C++ to Flex
return channelList.selectedItem.ChannelNum; //return value from Flex to C++
}
//VC++定义的调用Flex方法
//m_flashPlayer同样如上面所定义的那样,是flash player插件的对象
CString ret = m_FlashPlayer.CallFunction("<invoke name=\"sendToActionScript\" returntype=\"xml \"><arguments><string>aaa</string></arguments></invoke>");