如何实现IE中JS和VC之间的互相调用
2013-12-03 00:40
393 查看
脚本语言和编译型语言之间进行通信是通过IDispatch接口来行的,这里我对双接口的理论就不进行讨论,直接看看如何用WTL代码来实现。
首先定义如下的一个IDispatch实现:
以上代码中定义了一个CExternalDisp的组件,实现了IDispatch接口,当js脚本语言调用对象的某个方法时,会转成通过IDispatch的Invoke函数来调用,不同的函数对应不同的dispIdMember,而这个数字又是通过GetIDsOfNames来得到的。
有了CExternalDisp这个组件,还需要将其注册成为IE的exteranl对象。在IE控件的初始化部分进行设置,代码如下:
这样,JS脚本中的代码就可以访问window.external对象中得方法了。下面是html中js调用exteranl.abc的代码段:
可以看到在页面加载时调用了window.external.abc(1, 'ljw', 2.3);这个方法,还传递了参数。
当js的执行引擎解释这个语句时,会先去讲abc这个字符串送到GetIDsOfNames中去,获得对应的DISPID, 然后用这个DISPID在调用Invoke函数。我们在invoke函数对这个abc方法对应的dispid进行了处理,就能够给js进行结果反馈。通过实验,js函数中得参数是放在DISPPARAMS中传入Invoke的,而且好像是最右边的参数最先入栈。
首先定义如下的一个IDispatch实现:
1 class CExternalDisp: 2 public CComObjectRoot, 3 public IDispatch 4 { 5 public: 6 CExternalDisp(void); 7 ~CExternalDisp(void); 8 9 BEGIN_COM_MAP(CExternalDisp) 10 COM_INTERFACE_ENTRY(IDispatch) 11 END_COM_MAP() 12 13 HRESULT STDMETHODCALLTYPE GetTypeInfoCount( 14 /* [out] */ UINT *pctinfo) 15 { 16 return E_NOTIMPL; 17 } 18 19 HRESULT STDMETHODCALLTYPE GetTypeInfo( 20 /* [in] */ UINT iTInfo, 21 /* [in] */ LCID lcid, 22 /* [out] */ ITypeInfo **ppTInfo) 23 { 24 return E_NOTIMPL; 25 } 26 27 virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames( 28 /* [in] */ REFIID riid, 29 /* [size_is][in] */ LPOLESTR *rgszNames, 30 /* [in] */ UINT cNames, 31 /* [in] */ LCID lcid, 32 /* [size_is][out] */ DISPID *rgDispId) 33 { 34 CComBSTR bsName(*rgszNames); 35 if (bsName == L"abc") 36 { 37 *rgDispId = 2535; 38 return S_OK; 39 } 40 return E_NOTIMPL; 41 42 } 43 44 virtual /* [local] */ HRESULT STDMETHODCALLTYPE Invoke( 45 /* [in] */ DISPID dispIdMember, 46 /* [in] */ REFIID riid, 47 /* [in] */ LCID lcid, 48 /* [in] */ WORD wFlags, 49 /* [out][in] */ DISPPARAMS *pDispParams, 50 /* [out] */ VARIANT *pVarResult, 51 /* [out] */ EXCEPINFO *pExcepInfo, 52 /* [out] */ UINT *puArgErr) 53 { 54 if (dispIdMember == 2535) 55 { 56 for (int i = 0; i < pDispParams->cArgs; ++i) 57 { 58 if( pDispParams->rgvarg[i].vt == VT_INT) 59 i = i; 60 else 61 62 i = i; 63 64 } 65 66 67 MessageBox(NULL, L"sdjlkf", L"sdl", MB_OK); 68 return S_OK; 69 } 70 return E_NOTIMPL; 71 } 72 73 };
以上代码中定义了一个CExternalDisp的组件,实现了IDispatch接口,当js脚本语言调用对象的某个方法时,会转成通过IDispatch的Invoke函数来调用,不同的函数对应不同的dispIdMember,而这个数字又是通过GetIDsOfNames来得到的。
有了CExternalDisp这个组件,还需要将其注册成为IE的exteranl对象。在IE控件的初始化部分进行设置,代码如下:
1 CComPtr<IWebBrowser2> spWeb; 2 HRESULT hr = m_view.QueryControl(IID_IWebBrowser2, (void**)&spWeb ); 3 CComObject<CExternalDisp> *obj; 4 CComObject<CExternalDisp>::CreateInstance(&obj); 5 CComPtr<IDispatch> spDisp; 6 obj->QueryInterface(IID_IDispatch, (void**)&spDisp); 7 m_view.SetExternalDispatch(spDisp);
这样,JS脚本中的代码就可以访问window.external对象中得方法了。下面是html中js调用exteranl.abc的代码段:
<HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 8.0"> <TITLE></TITLE> <script type="text/javascript"> window.external.abc(1, 'ljw', 2.3); </script> </HEAD> <BODY> </BODY> </HTML>
可以看到在页面加载时调用了window.external.abc(1, 'ljw', 2.3);这个方法,还传递了参数。
当js的执行引擎解释这个语句时,会先去讲abc这个字符串送到GetIDsOfNames中去,获得对应的DISPID, 然后用这个DISPID在调用Invoke函数。我们在invoke函数对这个abc方法对应的dispid进行了处理,就能够给js进行结果反馈。通过实验,js函数中得参数是放在DISPPARAMS中传入Invoke的,而且好像是最右边的参数最先入栈。
相关文章推荐
- 如何实现IE中JS和VC之间的互相调用
- 如何实现IE中JS和VC之间的互相调用
- 如何用js实现,在一个页面有个输入文档框,然后点击查询按扭后,调用IE的查询功能在当前页面进行查询
- 基于 wke 的浏览器:如何实现 js 和 c++ 的互相调用
- IE下使用js调用系统activex实现文件下载
- VC调用IE控件里的JS ---by devinghou
- VC变量与matlab变量之间的转换,和互相调用
- doc 类 view类,frame类之间如何互相调用
- js之间是如何调用的?比如自己写的js,怎么调用jQuery框架中的js
- 如何通过js跨域调用ASP.NET Web API (请问如何实现在javascript中通过http get的方式跨域调用ASP.NET Web API?)
- Python 中如何利用import实现脚本之间的调用
- ASP.NET前台JS与后台CS函数如何互相调用
- 【转】JsBridge实现JavaScript和Java的互相调用
- 用js实现两个select下拉框之间的元素互相移动
- 在WebView中如何让JS与Java安全地互相调用
- 两个JS之间的函数互相调用
- js如何调用qq互联api实现第三方登录
- 在WebView中如何让JS与Java安全地互相调用
- JsBridge实现JavaScript和Android的互相调用
- 如何实现CAPP、CMainFrame、CViEW和CDOC之间相互调用?