zoukankan      html  css  js  c++  java
  • 如何实现IE中JS和VC之间的互相调用

    一直做IE相关的东西,但是发现对JS和VC之间如何调用不是很明白。虽然知道通过IDispatch接口可以在VC程序和JS之间进行交互,但是如何具体做一直有点模糊,所以就专门做了个实验,看看他们到底如何进行沟通。

    脚本语言和编译型语言之间进行通信是通过IDispatch接口来行的,这里我对双接口的理论就不进行讨论,直接看看如何用WTL代码来实现。

    首先定义如下的一个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的,而且好像是最右边的参数最先入栈。



  • 相关阅读:
    第十三周总结
    第十二周总结
    团队冲刺第十五天-KeepRunningAPP
    团队第一阶段冲刺评价
    团队项目KeepRunning第一阶段成果展示
    团队冲刺第十四天-KeepRunningAPP
    第十一周总结
    团队冲刺第十三天-KeepRunningAPP
    CVPR2018关键字生成词云图
    Delphi APP 開發入門(八)SQLite資料庫
  • 原文地址:https://www.cnblogs.com/kwliu/p/2195894.html
Copyright © 2011-2022 走看看