如何实现IE中JS和VC之间的互相调用

引用: http://www.cnblogs.com/kwliu/archive/2011/09/29/2195894.html

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

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

首先定义如下的一个IDispatch实现:

class CExternalDisp:
    public CComObjectRoot,
    public IDispatch
{
public:
    CExternalDisp(void);
    ~CExternalDisp(void);

    BEGIN_COM_MAP(CExternalDisp)
        COM_INTERFACE_ENTRY(IDispatch)
    END_COM_MAP()

     HRESULT STDMETHODCALLTYPE GetTypeInfoCount(
    /* [out] */ UINT *pctinfo)
    {
        return E_NOTIMPL;
    }

    HRESULT STDMETHODCALLTYPE GetTypeInfo(
        /* [in] */ UINT iTInfo,
        /* [in] */ LCID lcid,
        /* [out] */ ITypeInfo **ppTInfo)
    {
        return E_NOTIMPL;
    }

    virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(
        /* [in] */ REFIID riid,
        /* [size_is][in] */ LPOLESTR *rgszNames,
        /* [in] */ UINT cNames,
        /* [in] */ LCID lcid,
        /* [size_is][out] */ DISPID *rgDispId)
    {
        CComBSTR bsName(*rgszNames);
        if (bsName == L"abc")
        {
            *rgDispId = 2535;
            return S_OK;
        }
        return E_NOTIMPL;

    }

    virtual /* [local] */ HRESULT STDMETHODCALLTYPE Invoke(
        /* [in] */ DISPID dispIdMember,
        /* [in] */ REFIID riid,
        /* [in] */ LCID lcid,
        /* [in] */ WORD wFlags,
        /* [out][in] */ DISPPARAMS *pDispParams,
        /* [out] */ VARIANT *pVarResult,
        /* [out] */ EXCEPINFO *pExcepInfo,
        /* [out] */ UINT *puArgErr)
    {
        if (dispIdMember == 2535)
        {
            for (int i = 0; i < pDispParams->cArgs; ++i)
            {
                if( pDispParams->rgvarg[i].vt == VT_INT)
                    i = i;
                else

                    i = i;

            }

            MessageBox(NULL, L"sdjlkf", L"sdl", MB_OK);
            return S_OK;
        }
        return E_NOTIMPL;
    }
};

以上代码中定义了一个CExternalDisp的组件,实现了IDispatch接口,当js脚本语言调用对象的某个方法时,会转成通过IDispatch的Invoke函数来调用,不同的函数对应不同的dispIdMember,而这个数字又是通过GetIDsOfNames来得到的。

有了CExternalDisp这个组件,还需要将其注册成为IE的exteranl对象。在IE控件的初始化部分进行设置,代码如下:

CComPtr<IWebBrowser2> spWeb;
HRESULT hr = m_view.QueryControl(IID_IWebBrowser2, (void**)&spWeb );
CComObject<CExternalDisp> *obj;
CComObject<CExternalDisp>::CreateInstance(&obj);
CComPtr<IDispatch> spDisp;
obj->QueryInterface(IID_IDispatch, (void**)&spDisp);
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的,而且好像是最右边的参数最先入栈。

时间: 2024-08-28 10:31:31

如何实现IE中JS和VC之间的互相调用的相关文章

unity中js脚本与c#脚本互相调用

unity中js脚本与c#脚本互相调用 test1.js function OnGUI() { if(GUI.Button(Rect(25,25,100,30),"JS Call CS" )) { var c = gameObject.GetComponent("test2"); c.PrintTest(); } } function testPrint() { print("CS Call JS"); } test2.cs using Unit

JS与webview之间的互相调用。

iOS: 同步 NSString * shareContent = [self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"UP.M.Share.getData(%ld, 1)", (long)channel]]; Android: 异步调用, function hareContent_Android(channel) { getShareData(channel, functi

js和angularjs之间的相互调用

方法一 var element = angular.element($document.getElementById("app")); var controller = element.controller(); var scope = element.scope(); //调用方法 scope.sub1(); //如果需要重新绑定 scope.$apply(); //调用字段 scope.field1; angular.element(domElement).scope() to g

网页开发的阶段总结(四)--JS与PHP之间大数据的传送

在前面 的网页开发的阶段总结(三)中,我们知道JS与PHP之间直接互相调用,往往有很多不便,而且一次只能传送一个数据结果进行返回.而通过ajax方法可以实现JS一次性读取php的所传送过来的大量数据.通过提交表单的方式,让php可以一次性读取JS的大量数据. 1.借用AJAX方法,通过php读取数据库将大量数据显示在网页客户端上. a.页面一加载完,执行函数Gett(),代码如下: <html> <head> <meta http-equiv="Content-Ty

CeF3开发者系列之外篇——IE中JS与C++交互

使用IE内核开发客户端产品,系统和前端页面之间的交互,通常给开发和维护带来很大的便利性.但操作系统和前端之间的交互却是比较复杂的.具体来说就是脚本语言和编译语言的交互.在IE内核中html和css虽然不兼容,但是IE编程接口是完全一样的,这得益于微软的COM组件的结构化设计和实现.所以与IE交互,必须得先说一下COM,COM全称组件对象模型(Component Object Model). COM的基本思想很简单,所有的组件模块都提供一个最根本的接口, IUnkown,它有三个方法,AddRef

ios7中 丰富多彩的UIViewController之间的切换

转载自:http://onevcat.com/2013/10/vc-transition-in-ios7/ 毫无疑问,ViewController(在本文中简写为VC)是使用MVC构建Cocoa或者CocoaTouch程序时最重要的一个类,我们的日常工作中一般来说最花费时间和精力的也是在为VC部分编写代码.苹果产品是注重用户体验的,而对细节进行琢磨也是苹果对于开发者一直以来的要求和希望.在用户体验中,VC之间的关系,比如不同VC之间迁移和转换动画效果一直是一个值得不断推敲的重点.在iOS7中,苹

node.js笔记——文件之间的引入

node.js的基础语法就是JavaScript的语法,所以对于懂得javascript的同学来说要容易一些,至于环境的配置也要相对简单很多,可以访问官方文档进行安装.这里分享一下我在学习中总结的一些东西,这是第一篇先来说说文件之间如何进行引入并互相使用变量及函数. 码缘»node.js笔记——文件之间的引入 http://www.ithome.ren/2017/05/31/node-js1.html

iOS开发中视图控制器ViewControllers之间的数据传递

iOS开发中视图控制器ViewControllers之间的数据传递 这里我们用一个demo来说明ios是如何在视图控制器之间传递重要的参数的.本文先从手写UI来讨论,在下一篇文章中讨论在storyboard中传递数据. 首先新建一个空工程,并添加一个根视图控制器类,如下图所示: # 在函数didFinishLunchingWithOption中添加几行代码,完成后如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 - (BOOL)application:(UIApplication

Android中Fragment和Activity之间的互操作代码例子

摘要 本文介绍了Android中一个Activity中有多个Fragment的情况下,Fragment之间如何通过Activity进行互操作. 源代码 源代码地址为:http://download.csdn.net/detail/logicteamleader/8931199 源代码使用ADT编写,ADT版本为2014,Android版本为android-22. 技术要点 1.在Activity中的多个Fragment之间要互操作,一定要通过此Activity,不能直接通信: 2.在Activi