浏览器内ActiveX嵌套Flash正常交互的方法
技术领域
本发明涉及浏览器内ActiveX嵌套Flash正常交互的方法。
背景技术
Flash动画主要由矢量图形组成,矢量图形具有储存容量小,并且在缩放时不会失真的优点。利用Flash可以方便地做出炫丽的画面效果,而Flash本身具有强大的交互优势,通过AS脚本可以随心所欲的对其进行编程,正因为以上优点,Flash已经越来越多地作为其它软件的UI(界面)来使用,通过Flash来作为程序UI,不仅可以使得软件获得非常漂亮的画面效果,另外因为Flash的独立性,可以将程序的界面部分与软件的开发分离开来,使得程序的开发更加快捷方便。在对画面要求比较高的三维游戏中,已经越来越多地使用Flash作为UI,而网页游戏则直接使用Flash开发而成。通过相关接口和特定的方式,Flash中使用AS3.0编写的函数可以便捷的回调外部调用程序中的函数,而外部软件可以直接通过CallFunction调用Flash中使用AS3.0开发的函数。
但是,当外部调用程序本身就是ActiveX控件,嵌套在浏览器中使用时,外部调用程序将无法通过CallFunction接口来调用同样作为控件的Flash的函数接口,如果调用将造成异常导致程序崩溃。这时由于浏览器为了浏览器安全而禁止了第三方控件的通信,直接屏蔽了CallFunction函数的调用。
发明内容
本发明方法所解决的技术问题在于使用一种程序容器的方式,保证在浏览器中使用ActiveX控件,而该ActiveX控件中又嵌套使用Flash时,能够保证Flash的CallFunction函数能够正常使用。
本发明具体包括如下步骤:
步骤1,使用Visual Studio创建一个Visual C++项目,项目类型为MFC ActiveX控件,代号为模块A,作为容器,根据应用的需要设置相应的接口和接口参数,统称为接口C,供浏览器调用(如JavaScript),参循MFC(微软基础类库,Microsoft Foundation Classes,简称MFC)标准方法来进行接口的添加和设置,但在这里仅仅创建出接口和相应该接口需要的参数,而实际上不写入任何该接口功能实现的代码。
步骤2,创建嵌有Flash控件的可执行程序(该程序功能可根据自身应用需求自行设定,功能接口根据本发明规则),代号为模块B,在模块B中实现模块A的接口C相对应的响应函数,统称为函数D,函数D中实现接口C中的实际应用功能,并设定模块B的类名为:Win32Application;
步骤3,将模块B设定为模块A的子程序模块,模块A作为模块B的父窗口模块,模块A的窗口事件将会因为父子窗口关系自动转发给模块B(参照Windows窗口标准机制);
步骤4,同步模块A的窗口大小改变到模块B;
步骤5,建立接口C和函数D的交互连接,接口C包括两个类型:方法和回调,浏览器(如JavaScript)调用接口C时,能直接响应函数D(方法)或者函数D将结果传递给接口C(回调),继而返回给浏览器(如JavaScript);
步骤6,模块A销毁时,发送WM_CLOSE消息(即关闭消息)给模块B,作关闭同步处理。WM_CLOSE消息为Windows的标准窗口消息,当任何窗口接收到该消息时,窗口即执行关闭本窗口的操作。
步骤3包括:
步骤3-1,根据类名:Win32Application,通过FindWindow API获取模块B的窗口句柄;FindWindow是Win32标准接口(API),通过该接口,可以通过程序的类名或者程序窗口的标题获取该程序的控制句柄(HANDLE),该步骤正是使用该API,通过模块B的类名,让模块A获取模块B的控制句柄,通过该句柄,实现模块A对模块B的控制。步骤3-2,将模块B的父窗口设置为模块A,模块A作为模块B的父窗口模块,模块A的窗口事件将会因为父子窗口关系自动转发给模块B。
步骤4包括:
步骤4-1,获取模块A的窗口尺寸;
步骤4-2,将模块B的窗口尺寸设定为步骤4-1中获得的窗口尺寸,保证模块B的窗口与模块A的窗口大小一致。
步骤5包括:
步骤5-1,在模块B中重载WM_COPYDATA映射函数;WM_COPYDATA是Windows窗口间的一个标准消息,该消息允许一个程序向另一个程序传递数据。模块B重载了WM_COPYDATA消息后会生成该消息的映射函数,该函数中即能够接收其它程序发送过来的WM_COPYDATA消息并进行处理。
步骤5-2,模块A中的接口C本身不做功能的实现,当浏览器(如JavaScript)调用接口C时,接口C会通过SendMessage函数发送一个WM_COPYDATA消息给B模块,而接口中的参数都存放在COPYDATASTRUCT结构体中随消息发出。SendMessage是Windows的一个标准的API,用于给指定的程序发送消息。COPYDATASTRUCT为一个数据结构体,其数据结构为:
dwData:表示消息类型,使用整型,
cbData:表示参数的长度,
lpData:表示参数的内存地址;
步骤5-3,模块B接收WM_COPYDATA映射函数消息的响应:接收到WM_COPYDATA消息后,解析消息中传递过来的COPYDATASTRUCT数据,通过数据中的dwData(整型)来判断消息类型,根据类型来确定需要响应的函数D,而传递过来的参数指针地址都存放在内存地址lpData中,可以直接转换为传递过来时的数据类型并进行使用。步骤5中所述建立接口C和函数D的交互连接,浏览器调用接口C时,能直接响应函数D或者函数D将结果传递给接口C,其中函数D将结果传递给接口C的过程,包括如下步骤:
步骤5-4,获取属性的请求由外部JavaScript发起调用接口C,接口C在执行该获取属性的方法时,使用SendMessage函数向模块B发送请求WM_COPYDATA消息,消息中的参数为COPYDATASTRUCT结构体数据,数据中的dwData消息类型为自行定义的获取属性的消息,模块B在收到该消息后,执行获取属性的操作即执行函数D,获取后,模块A和模块B将通过共享内存的方法将属性值从模块B传给模块A,最终传递给外部调用的程序JavaScript;
步骤5-5,模块B处理如下:模块B中创建共享内存并把需要传递的值拷贝至该共享内存首地址,在拷贝完成后通知模块A,模块A再从该内存中将该值取走。
如果在浏览器中直接调用一个内嵌Flash的ActiveX控件,则ActiveX与Flash交互的CallFunction函数就会失效并崩溃,但如果在一个独立的应用程序中嵌入Flash,则CallFunction不受影响,因此本发明思路就是将Flash嵌入到一个独立的应用程序(代号B)中,再将该程序(B)作为子程序嵌入到ActiveX对象(代号A)中,这样A作为标准的ActiveX控件正常被浏览器调用,而Flash又是嵌入在独立的程序(B)中,与浏览器没有任何的关联,在这种情况下,Flash的CallFunction就能够正常使用了。下面要解决的事情就是打通A和B之间的关联,使得A和B使用起来就是一个程序,能够正常使用ActiveX定义的方法以及A中接收的键盘鼠标事件并在B中响应、能过A直接获取B的属性、在A中响应B的回调。
(1)响应方法
响应的方法包括ActiveX暴露给JavaScript的方法以及鼠标单击、双击、滚轮事件以及键盘事件,所有这些方法和事件都由ActiveX程序(A)接受,A接受后不作处理,直接转发给B,B收到这些消息后作相应的程序处理
(2)获取属性
在ActiveX对象(A)中,会有相应的获取属性的函数暴露给JavaScript,但A不是主体程序,并没有相应的属性,因此A在收到获取属性的调用函数后也不做处理,直接把获取属性的请求发送给B,B在收到获取属性的调用请求后,通过共享内存的方法把属性传给A
有益效果:
目前解决此类问题主要有两种方式:
(1)使用网络通信的方式,通过Socket形式进行消息交互,该方式依赖于网卡以及网络环境,并且由于本身在IE中打开,极易造成消息的不稳定。
(2)使用第三方脚本的形式来传递消息,本身通过第三方脚本在IE环境中对安全的级别有要求,并且该方式在处理消息时,对双方的开发依赖都很强。而使用本发明的方式,则可以将Flash的开发与调用其程序的发开发独立开来,不用关心中间的消息传递部分
另外,使用本发明的方式,不仅可以解决程序调用Flash控件时造成的CallFunction异常问题,同时可以将开发的程序与IE环境的关系降低,只要定义好通信的消息形式,不论容器程序(代号A)是基于IE的ActiveX,还是基于Firefox或是Chrome,只要各自的消息接口一致,将不需要将主体程序开发为三个版本,而只要开发相应的容器程序即可。
附图说明
下面结合附图和具体实施方式对本发明做更进一步的具体说明,本发明的上述或其他方面的优点将会变得更加清楚。
图1为本发明中浏览器与模块A和模块B之间的关系图。
图2为浏览器与模块A及模块B之间消息传递示意图。
具体实施方式
下面结合附图及实施例对本发明做进一步说明。
如图1和图2所示,本发明公开了浏览器内ActiveX嵌套Flash正常交互的方法,具体包括如下步骤:
步骤1,使用Visual Studio创建一个Visual C++项目,项目类型为MFC ActiveX控件,代号为模块A,作为容器,根据应用的需要设置相应的接口和接口参数,统称为接口C,供浏览器调用(如JavaScript),参循MFC标准方法来进行接口的添加和设置,但在这里仅仅创建出接口和相应该接口需要的参数,而实际上不写入任何该接口功能实现的代码。
步骤2,创建嵌有Flash控件的可执行程序(该程序功能可根据自身应用需求自行设定,功能接口根据本发法规则),代号为模块B,在模块B中实现模块A的接口C相对应的响应函数,统称为函数D,函数D中实现接口C中的实际应用功能,并设定模块B的类名为:Win32Application;
步骤3,将模块B设定为模块A的子程序模块,模块A作为模块B的父窗口模块,模块A的窗口事件将会因为父子窗口关系自动转发给模块B(参照Windows窗口标准机制);
步骤4,同步模块A的窗口大小改变到模块B;
步骤5,建立接口C和函数D的交互连接,接口C包括两个类型:方法和回调,浏览器(如JavaScript)调用接口C时,能直接响应函数D(方法)或者函数D将结果传递给接口C(回调),继而返回给浏览器(如JavaScript);
步骤6,模块A销毁时,发送WM_CLOSE消息(即关闭消息)给模块B,作关闭同步处理。WM_CLOSE消息为Windows的标准窗口消息,当任何窗口接收到该消息时,窗口即执行关闭本窗口的操作。
步骤3包括:
步骤3-1,根据类名:Win32Application,通过FindWindow API获取模块B的窗口句柄;FindWindow是Win32标准接口(API),通过该接口,可以通过程序的类名或者程序窗口的标题获取该程序的控制句柄(HANDLE),该步骤正是使用该API,通过模块B的类名,让模块A获取模块B的控制句柄,通过该句柄,实现模块A对模块B的控制。
步骤3-2,将模块B的父窗口设置为模块A,模块A作为模块B的父窗口模块,模块A的窗口事件将会因为父子窗口关系自动转发给模块B。
步骤4包括:
步骤4-1,获取模块A的窗口尺寸;
步骤4-2,将模块B的窗口尺寸设定为步骤4-1中获得的窗口尺寸,保证模块B的窗口与模块A的窗口大小一致。
步骤5包括:
步骤5-1,在模块B中重载WM_COPYDATA映射函数;WM_COPYDATA是Windows窗口间的一个标准消息,该消息允许一个程序向另一个程序传递数据。模块B重载了WM_COPYDATA消息后会生成该消息的映射函数,该函数中即可以接收其它程序发送过来的WM_COPYDATA消息并进行处理。
步骤5-2,模块A中的接口C本身不做功能的实现,当浏览器(如JavaScript)调用接口C时,接口C会通过SendMessage函数发送一个WM_COPYDATA消息给B模块,而接口中的参数都存放在COPYDATASTRUCT结构体中随消息发出。SendMessage是Windows的一个标准的API,用于给指定的程序发送消息。COPYDATASTRUCT为一个数据结构体,其数据结构为:
dwData:表示消息类型,使用整型,
cbData:表示参数的长度,
lpData:表示参数的内存地址;
步骤5-3,模块B接收WM_COPYDATA映射函数消息的响应:接收到WM_COPYDATA消息后,解析消息中传递过来的COPYDATASTRUCT数据,通过数据中的dwData(整型)来判断消息类型,根据类型来确定需要响应的函数D,而传递过来的参数指针地址都存放在内存地址lpData中,可以直接转换为传递过来时的数据类型并进行使用。
步骤5-4,获取属性的请求由外部JavaScript发起调用接口C,接口C在执行该获取属性的方法时,使用SendMessage函数向模块B发送请求WM_COPYDATA消息,消息中的参数为COPYDATASTRUCT结构体数据,数据中的dwData消息类型为自行定义的获取属性的消息,模块B在收到该消息后,执行获取属性的操作即执行函数D,获取后,模块A和模块B将通过共享内存的方法将属性值从模块B传给模块A,最终传递给外部调用的程序JavaScript;
步骤5-5,模块B处理如下:假设需要获取模块B中的名字:Name
在模块B中,通过CreateFileMapping()函数创建一个内存映射文件对象,如果创建成功则通过MapViewOfFile()函数将此文件映射对象的视图映射进地址空间,同时得到此映射视图的首址,此时就是创建了一个共享内存,并获取了该内存的地址,此时,只要将要传递的Name拷贝至该地址,即需要传递的内容被放进了共享内存。
当数据已经传递至共享内存后,此时模块B需要发送通知告诉模块A,数据已经传递完毕。
模块A在收到后,只需要从共享内存里把该值取走,即完成了数据从模块B到模块A的传递,此时模块A就可以使用该数据来响应相应的操作需求。
CreateFileMapping是Windows的一个标准API函数,为一个指定的文件创建或打开一个已命名或未命名的文件映射对象,告知系统文件映射对象需要多少物理存储器。
MapViewOfFile是Windows的一个标准API函数,功能是将一个文件映射对象映射到当前应用程序的地址空间。
本发明提供了浏览器内ActiveX嵌套Flash正常交互的方法,具体实现该技术方案的方法和途径很多,以上所述仅是本发明的优选实施方式,应当指出,对于本技术领域的普通技术人员来说,在不脱离本发明原理的前提下,还可以做出若干改进和润饰,这些改进和润饰也应视为本发明的保护范围。本实施例中未明确的各组成部分均可用现有技术加以实现。