IWebbrowser2中C++与JavaScript的交互调用

JS调用C++

IWebbrowser2中C++与JS交互主要处理IDispatch中的两个接口

1、GetIDsOfNames

这里主要是把需要调用JS函数给编一个号,为什么函数要编号呢?建议看看COM的原理,大概是C++实现的COM调用机制主要是用的虚函数表,但是其他的脚本语言中并没有这个玩意,其他脚本需要调用函数时,只能通过函数的ID来找到对应的函数。

那么我们就来给我们需要的函数一一编号:

函数列表的声明部分

struct _JS_FUNCTION{LPCTSTRlpName;DISPIDid;UINTnArgcCount;HRESULT (CMyWebEventHandler::*FUN)(DISPID, DISPPARAMS*, VARIANT*);};const _JS_FUNCTION funs[]={{ L"setAppState", DISPID_BASE+0, 4, &CMyWebEventHandler::OnGetAppState },{ L"OneClickInstall", DISPID_BASE+1, 5, &CMyWebEventHandler::OnOneClickInstall },//{ L"GetInstallState", DISPID_BASE+2, 1, &CMyWebEventHandler::OnGetInstallState },{ L"DownLoadFile", DISPID_BASE+2, 5, &CMyWebEventHandler::OnDownLoadFile },{ L"OpenSite", DISPID_BASE+3, 1, &CMyWebEventHandler::OnOpenSite },};根据函数名称对比,在我们的列表中的函数就给其编号STDMETHODIMP CMyWebEventHandler::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId){if(cNames == 0 || rgszNames == NULL || rgszNames[0] == NULL || rgDispId == NULL){return E_INVALIDARG;}for(int i = 0; i <sizeof(funs)/sizeof(_JS_FUNCTION) ; ++i) //枚举所有函数{if(_wcsicmp(rgszNames[0], funs[i].lpName) == 0){*rgDispId = funs[i].id;return S_OK;}}return E_INVALIDARG;}2、Invoke

函数的调用过程发生在这里。

这个接口传来函数的调用的标识是函数ID,那么只要是我们上面标识了的ID,,我们就根据其中记录的回调地址调用它的处理函数

STDMETHODIMP CMyWebEventHandler::Invoke( DISPID dispIdMember, REFIID riid, LCID lcid,WORD wFlags, DISPPARAMS* pDispParams,VARIANT* pVarResult, EXCEPINFO* pExcepInfo,UINT* puArgErr ){if ( dispIdMember<DISPID_BASE || dispIdMember>DISPID_BASE+4 )return E_NOTIMPL;if ( pDispParams->cArgs!=funs[dispIdMember-DISPID_BASE].nArgcCount )return E_INVALIDARG;for(UINT i = 0; i < pDispParams->cArgs; ++i){if((pDispParams->rgvarg[i].vt & VT_BSTR) == 0){return E_INVALIDARG;}}return (this->*(funs[dispIdMember-DISPID_BASE].FUN))(dispIdMember, pDispParams, pVarResult);}另外IE里的JS函数一定要写在window.external上面。

所以,需要返回对应的 this指针

HRESULT STDMETHODCALLTYPE CMyWebEventHandler::GetExternal( /* [out] */ IDispatch __RPC_FAR *__RPC_FAR *ppDispatch ){*ppDispatch=this;return S_OK;}C++调用JS

首先是获取函数对应的ID,然后还是Invoke传入函数ID和对应的参数信息

bool ExecJsFun( const wstring& lpJsFun, const vector<wstring>& params ){if ( NULL == m_pWebBrowser2 )return false;CComPtr<IDispatch> pDoc;HRESULT hr = m_pWebBrowser2->get_Document(&pDoc);if ( FAILED(hr) )return false;CComQIPtr<IHTMLDocument2> pDoc2=pDoc;if ( NULL == pDoc2 )return false;CComQIPtr<IDispatch> pScript;hr = pDoc2->get_Script(&pScript);if ( FAILED(hr) )return false;DISPID id = NULL;CComBSTR bstrFun(lpJsFun.c_str());hr = pScript->GetIDsOfNames(IID_NULL, &bstrFun, 1, LOCALE_SYSTEM_DEFAULT, &id);if ( FAILED(hr) )return false;DISPPARAMS dispParams;memset(&dispParams, 0, sizeof(DISPPARAMS));int nParamCount= params.size();if ( nParamCount > 0 ){dispParams.cArgs=nParamCount;dispParams.rgvarg=new VARIANT[nParamCount];for (int i=0; i<nParamCount; ++i ){const wstring& str = params[nParamCount-1-i];CComBSTR bstr(str.c_str());bstr.CopyTo(&dispParams.rgvarg[i].bstrVal);dispParams.rgvarg[i].vt= VT_BSTR;}}EXCEPINFO execInfo;memset(&execInfo, 0, sizeof(EXCEPINFO));VARIANT vResult;UINT uArgError = (UINT)-1;hr = pScript->Invoke(id, IID_NULL, 0, DISPATCH_METHOD, &dispParams, &vResult, &execInfo, &uArgError);delete[] dispParams.rgvarg;if ( FAILED(hr) )return false;return true;}

怕走崎岖路,莫想登高峰。

IWebbrowser2中C++与JavaScript的交互调用

相关文章:

你感兴趣的文章:

标签云: