Webbrowser用中JS调用c++的函数

2017-02-06  本文已影响159人  晓函
#pragma once
#include "..\Head.h"

//_bstr_t需要的头文件
#include "comutil.h"
#pragma comment(lib, "comsuppw")

class ClientCall :public IDispatch
{
    long _refNum;
public:
    ClientCall()
    {
        _refNum = 1;
    }
    ~ClientCall(void)
    {
    }
public:

    // IUnknown Methods

    STDMETHODIMP QueryInterface(REFIID iid, void**ppvObject)
    {
        *ppvObject = NULL;
        if (iid == IID_IUnknown)    *ppvObject = this;
        else if (iid == IID_IDispatch)    *ppvObject = (IDispatch*)this;
        if (*ppvObject)
        {
            AddRef();
            return S_OK;
        }
        return E_NOINTERFACE;
    }

    STDMETHODIMP_(ULONG) AddRef()
    {
        return ::InterlockedIncrement(&_refNum);
    }

    STDMETHODIMP_(ULONG) Release()
    {
        ::InterlockedDecrement(&_refNum);
        if (_refNum == 0)
        {
            delete this;
        }
        return _refNum;
    }

    // IDispatch Methods

    HRESULT _stdcall GetTypeInfoCount(
        unsigned int * pctinfo)
    {
        return E_NOTIMPL;
    }

    HRESULT _stdcall GetTypeInfo(
        unsigned int iTInfo,
        LCID lcid,
        ITypeInfo FAR* FAR* ppTInfo)
    {
        return E_NOTIMPL;
    }

    HRESULT _stdcall GetIDsOfNames(
        REFIID riid,
        OLECHAR FAR* FAR* rgszNames,
        unsigned int cNames,
        LCID lcid,
        DISPID FAR* rgDispId
        )
    {
        //对比函数名,设置一个dispId用与识别

        if (lstrcmp(rgszNames[0], L"CppCall") == 0)
        {
            //网页调用window.external.CppCall时,会调用这个方法获取CppCall的ID
            *rgDispId = 100;
        }
        if (lstrcmp(rgszNames[0], L"AddGoodsToList") == 0)
        {
            *rgDispId = 101;
        }
        return S_OK;
    }

    HRESULT _stdcall Invoke(
        DISPID dispIdMember,
        REFIID riid,
        LCID lcid,
        WORD wFlags,
        DISPPARAMS* pDispParams,
        VARIANT* pVarResult,
        EXCEPINFO* pExcepInfo,
        unsigned int* puArgErr
        )
    {
        //通过识别之前设置的dispId,调用对应函数
        if (dispIdMember == 100)
        {
            //网页调用CppCall时,或根据获取到的ID调用Invoke方法
            CppCall();
        }

        if (dispIdMember == 101)
        {
            wstring args = (_bstr_t)pDispParams->rgvarg[0];
            //网页调用CppCall时,或根据获取到的ID调用Invoke方法
            AddGoodsToList(args);
        }
        return S_OK;
    }

    //测试函数
    void CppCall()
    {
        MessageBox(NULL, L"您调用了CppCall", L"提示(C++)", 0);
    }

    //添加商品
    void AddGoodsToList(wstring args){
          MessageBox(NULL, args.c_str(), L"AddGoodsToList参数", 0);
        }

};

使用方法

//在duilib中,使用方法
class MainWnd: public CContainerUI,public CWebBrowserEventHandler
{
public:
    ClientCall *pClientCall_;
    CWebBrowserUI* m_pBrowser;

    MainWnd(){
        m_pBrowser = NULL;
        pClientCall_ = new ClientCall();
    }
    //初始化CWebBrowserUI控件
    void InitControl(){
        m_pBrowser = static_cast<CWebBrowserUI*>(...));
        //所有webbrowser事件和接口关联到当前this对象
        if (m_pBrowser) 
            m_pBrowser->SetWebBrowserEventHandler(this);
    }
    //继承GetExternal,以便JS调用c++,window.external.CppCall();
    virtual HRESULT STDMETHODCALLTYPE GetExternal(IDispatch **ppDispatch){
        //重写GetExternal返回一个ClientCall对象
        *ppDispatch = pClientCall_;
        //计数器+1(很重要)
        pClientCall_->AddRef();
        return S_OK;
    }

};

//JS代码

window.external.AddGoodsToList('this a cat');
上一篇 下一篇

猜你喜欢

热点阅读