ActiveX异步回调JavaScript-阿里云开发者社区

开发者社区> double2li> 正文

ActiveX异步回调JavaScript

简介: ActiveX异步回调JavaScript       开发环境:VC6.0。       背景知识:COM/ActiveX/JavaScript/MFC/Thread         想必用过Ajax的童鞋们都知道xmlhttp这个东西吧,通过设定onreadystatechange属性,我们就可以指定他状态改变的回调函数,当状态改变时,ActiveX控件就会调用我们通过onreadystatechange属性制定的回调函数。
+关注继续查看

ActiveX异步回调JavaScript

      开发环境:VC6.0

      背景知识:COM/ActiveX/JavaScript/MFC/Thread

 

      想必用过Ajax的童鞋们都知道xmlhttp这个东西吧,通过设定onreadystatechange属性,我们就可以指定他状态改变的回调函数,当状态改变时,ActiveX控件就会调用我们通过onreadystatechange属性制定的回调函数。从而就出现了Ajax给我们带来的精彩。关于Ajax的技术我们这里不做讨论,我们的目的就是实现像xmlhttp这样具有异步回调JavaScript功能的ocx控件来。

 

      Let’s go!

 

1.      建立MFC ActiveX Control(方法略)

2.      ClassWizard中添加属性callbackfunction属性,并为该属性生成getset方法。我们将在ActiveX控件中开启线程,线程执行完后将调用通过该属性执行的JavaScript函数。在该实例中,通过callbackfunction属性指定的JavaScript函数必须是返回值是void的,并且含有一个short类型的参数的函数。

3.      我们需要一个方法来触发回调函数,添加方法Invoke包含一个short类型的参数param。在这个函数里将开启一个线程进行运算,然后返回计算结果。并把结果以回调函数的形式调用JavaScript的函数。

4.      Invoke方法中开启线程。进行计算。线程同步的方法采用PostMessage自定义消息。这个很重要,否则的话,我们在线程中操作界面控件是不正确的。(我就是忘记了进行线程同步才多走了好多弯路)

#define WM_THREADFIREEVENT WM_USER+101

void f(void * r)

{

      CThirdCtrl* p = (CThirdCtrl*)r;

      Sleep(5000);

      p->m_param +=10;

       PostMessage(p->m_hWnd,WM_THREADFIREEVENT,(WPARAM)NULL,(LPARAM)NULL);

      return;

}

 

void CThirdCtrl::invoke(short param)

{

      m_param = param;

      _beginthread(f, 0, (void*)(this));

}

 

5.      添加THREADFIREEVENT消息的消息映射函数:

ON_MESSAGE(WM_THREADFIREEVENT,OnFireEventForThread)

 

      6.   实现函数OnFireEventForThread

LRESULT CThirdCtrl::OnFireEventForThread(WPARAM wParam, LPARAM lParam)

{

   //FireLengthyProcessDone();

      InvokeScript ();

      return TRUE;

}

7.  在实现InvokeScript前,先说一个重要的东西,就是OnSetClientSite这是一个CThirdCtrl的父类ColeControl的一个虚方法。我们需要重写他来获得IWebBrowser2指针,有了IWebBrowser2我们就可以为所欲为了。比方说获得document对象,获得html中的elements,设定他们的属性,调用方法。也可以执行页面中的JavaScript函数。

     为获得顶层IWebBrowser2引用,从客户站点获取IServiceProvider接口并且执行一个QueryService 操作获取IID_IServiceProvider服务:SID_STopLevelBrowser (这在Shlguid.h中定义);对第二个IServiceProvider,执行一个QueryService获取IID_IWebBrowser2服务:SID_SWebBrowserApp.

     上代码:

void CThirdCtrl::OnSetClientSite()

{

     

     IOleClientSite*  pClientSite  =  GetClientSite(); 

     

     HRESULT  hr  =  S_OK; 

     IServiceProvider  *isp,  *isp2  =  NULL;//用于导航DHTML对象层次,作用就是提供服务 

     

     if  (!pClientSite) 

     

      if(browser!=NULL)

      {

             browser->Release();

             browser = NULL;

      }

      return;//  !S_OK; 

     

     else 

     

      hr  =  pClientSite->QueryInterface(IID_IServiceProvider,  reinterpret_cast<void  **>(&isp)); 

      if  (FAILED(hr))   

      

             hr  =  S_OK; 

             goto  cleanup; 

      

      

      hr  =  isp->QueryService(SID_STopLevelBrowser,  IID_IServiceProvider,  reinterpret_cast<void  **>(&isp2)); 

      if  (FAILED(hr)) 

      

             hr  =  S_OK; 

             goto  cleanup; 

      

      

      //获得浏览器 

      hr  =  isp->QueryService(SID_SWebBrowserApp,  IID_IWebBrowser2,  reinterpret_cast<void  **>(&browser));

      if  (FAILED(hr))   

      

             hr  =  S_OK; 

             goto  cleanup; 

      

      

cleanup: 

      //  Free  resources. 

      if(isp!=NULL)

      {

             isp->Release();

             isp = NULL;

      }

      if(isp2!=NULL)

      {

             isp2->Release();

             isp2 = NULL;

      }

      return;//  hr; 

     

     

     return;//  hr;

     

}

             同样的道理,如果我们是ATL做的ActiveX,则需要重写

STDMETHODIMP  CThirdCtrl::SetClientSite()

这个方法。

8.   下面就是最关键的InvokeScript函数的实现,我们在这里使用上面获取到的IWebBrowser2指针来获取document对象,然后获取Idispatch接口的script对象,然后调用Idispatch接口的Invoke方法。就可以调用JavaScript了。Idispatch接口真是强大啊。

废话少说,上代码:

void  CThirdCtrl::InvokeScript() 

if(!browser) 

       if(browser!=NULL)

       {

              browser->Release();

              browser = NULL;

       }

       return; 

CComPtr<IHTMLDocument2> m_spDoc; 

HRESULT hr = browser->get_Document((IDispatch**)&m_spDoc);   

if(FAILED(hr)) 

       throw(""); 

CComPtr<IDispatch> pScript; 

hr = m_spDoc->get_Script(&pScript); 

if(FAILED(hr)) 

       throw(""); 

CComBSTR  bstrMember(m_callbackfunction);   

DISPID  dispid; 

hr=pScript->GetIDsOfNames(IID_NULL,&bstrMember,1,LOCALE_SYSTEM_DEFAULT,&dispid); 

//  设置函数参数 

DISPPARAMS  dispparams; 

memset(&dispparams,0,sizeof(dispparams)); 

dispparams.cArgs = 1;//表示参数的计数。 

dispparams.rgvarg = new VARIANT[dispparams.cArgs];//表示对参数数组的引用。 

for(int i = 0; i < 1; i++) 

       //CComBSTR bstr = "111";  //  back  reading 

       //bstr.CopyTo(&dispparams.rgvarg[i].bstrVal); 

       dispparams.rgvarg[i].iVal = m_param;

       dispparams.rgvarg[i].vt = VT_I2; 

dispparams.cNamedArgs =0;//表示命名参数的计数。 

EXCEPINFO excepInfo; 

memset(&excepInfo,0,sizeof(excepInfo)); 

CComVariant vaResult; 

UINT nArgErr = (UINT)-1;  //  initialize  to  invalid  arg 

hr = pScript->Invoke(dispid, IID_NULL,0,DISPATCH_METHOD,&dispparams,&vaResult,&excepInfo,&nArgErr); 

这样,ActiveX控件就完成了。

9.      编写html页面代码。打开Microsoft ActiveX Control Pad,插入控件。然后编写JavaScript代码。

<HTML>

<HEAD>

<TITLE>New Page</TITLE>

</HEAD>

<BODY>

   <SCRIPT LANGUAGE="JavaScript" >

function invoke()

{

       Third1.callbackfunction = "callback";

       Third1.invoke(2);

       alert("begin invoke");

}

function callback(param)

{

       alert(param);

}

 

   </SCRIPT>

<OBJECT ID="Third1" WIDTH=100 HEIGHT=51

 CLASSID="CLSID:E9D38528-0F4E-468B-858D-69905F16942F">

   <PARAM NAME="_Version" VALUE="65536">

   <PARAM NAME="_ExtentX" VALUE="2646">

   <PARAM NAME="_ExtentY" VALUE="1323">

   <PARAM NAME="_StockProps" VALUE="0">

</OBJECT>

<input type="button" value="test" onclick="invoke();" />

</BODY>

</HTML>

10.  测试:打开浏览器,打开test.html页面。点击“test“按钮,将会先显示对话框begin invoke,然后过5秒钟再显示对话框12

11.  调试方法:我们可以直接调试浏览器。浏览器加载了控件,然后我们调用控件的方法,这时会自动触发我们在工程中设置的断点。在

project---settings---debug---executable for debug sessions设置浏览器的exe文件的路径。我用的世界之窗浏览器。所以值设置为:C:\Program Files\TheWorld\TheWorld.exe

如果你用IE浏览器,可设置为:C:\Program Files\Internet Explorer\iexplore.exe

 

说明:

1.   上述控件与xmlhttp不同的地方是callbackfunction我传的是一个字符串,而xmlhttp传的是一个JavaScript的函数指针。

2.   COM中的线程模型不在本文讨论范围之内。还有浏览器安全问题和打包CAB的问题也不在本文讨论范围之内。

参考:

http://vcfaq.mvps.org/com/1.htm

http://vcfaq.mvps.org/com/11.htm

http://support.microsoft.com/kb/q157437/

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
4012 0
使用java传参调用exe并且获取程序进度和返回结果的一种方法
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 在某个项目中需要考虑使用java后台调用由C#编写的切图程序(exe),并且前端能够获取到切图的进度和相关描述信息。
2159 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
3959 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
5681 0
MFC Activex OCX Javascript 互相访问问题,线程回调javascript
//比较好的教程    ocx 在 win7 系统会出现注册需要管理员权限的问题,这时候需要用管理员身份运行 cmd,然后运行 regsvr32注册。   很麻烦   尝试使用 nsis 做成安装包, 采用 regdll 注册 ocx, 成功。
1114 0
Java回调函数的理解
所谓回调,就是客户程序C调用服务程序S中的某个函数A,然后S又在某个时候反过来调用C中的某个函数B,对于C来说,这个B便叫做回调函数。例如Win32下的窗口过程函数就是一个典型的回调函数。一般说来,C不会自己调用B,C提供B的目的就是让S来调用它,而且是C不得不提供。
954 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
10716 0
回调函数透彻理解Java
回调函数,第一次见是在Java编程思想中,以及后来的观察者模式也应用了回调函数的思想。但是一直都没有重视,终于在一次面试的时候吃亏了,越来越理解为什么很多人说Java编程思想这本书要一遍遍的看,吃透!         首先在网络上搜索很多文章介绍什么是回调函数,看的云里雾里的。
752 0
从零开始学_JavaScript_系列(四)——jquery(基础,选择器,触发条件,动画,回调函数)
jQuery语法   (1)引用jquery文件及下载库: http://jquery.com/download/ 下载 Download the compressed, production jQuery 2.2.2 这个是用户版的,已经被精简和压缩。 然后使用 &lt;script src="jquery.js"&gt;&lt;/script&gt; 来启动这个库文件
1298 0
Java:回调机制
引用:http://blog.sina.com.cn/s/blog_48cf38890100go6x.html 1.  什么是回调函数    回调函数(callback Function),顾名思义,用于回调的函数。
731 0
+关注
double2li
一个在IT行业摸爬滚打的老司机
2870
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载