给自己看的,方便以后查阅!对某些人,如果要加注释你才能看得懂,请绕行。
HTML中的测试代码
//测试JS调用C++,无参函数
function testCallFunc() {
window.cat8637.TheFuncNoParam();
}
//测试JS调用C++,带两个参数函数
function testCallFunc2() {
var arg1 = document.getElementById("func2_input1").value;
var arg2 = document.getElementById("func2_input2").value;
alert(window.cat8637.TheFuncHave2Params(arg1,arg2));
//正确返回"head and tail"字符串。
}
第一部份:
CDialogEx继承类中加入下面属性
CComPtr<JSObject> m_jsObject;
并在构造class的时候加入下面的代码
m_jsObject = new JSObject();
第二部份:
void CTestWebBrowser_J2CDlg::NavigateComplete2Explorer1(LPDISPATCH pDisp, VARIANT* URL)
{
AddCustomObject(L"cat8637");
}
HRESULT CTestWebBrowser_J2CDlg::AddCustomObject(std::wstring objName)
{
HRESULT hRes;
CComPtr<IDispatch> pDocDisp;
CComQIPtr<IHTMLDocument2> pHtmlDoc2;
CComQIPtr<IHTMLWindow2> pWindow;
//Step1:Get pWindow
IUnknown* pUnk = m_webBrowser.GetControlUnknown();
if (pUnk==NULL)
return E_FAIL;
CComQIPtr<IWebBrowser2> pWeb;
hRes = pUnk->QueryInterface(IID_IWebBrowser2,(void**)&pWeb);
if (FAILED(hRes) || pWeb==NULL)
return hRes;
hRes = pWeb->get_Document(&pDocDisp);
if(FAILED(hRes) || pDocDisp==NULL)
return hRes;
hRes = pDocDisp->QueryInterface(IID_IHTMLDocument2, (void**)&pHtmlDoc2);
if(FAILED(hRes) || pHtmlDoc2==NULL)
return hRes;
hRes = pHtmlDoc2->get_parentWindow(&pWindow);
if(FAILED(hRes) || pWindow==NULL)
return hRes;
//Step2: set JS object name
DISPID dispid;
IDispatchEx *pWndEx;
hRes = pWindow->QueryInterface(&pWndEx);
if (FAILED(hRes)||pWndEx==NULL)
return hRes;
hRes = pWndEx->GetDispID((BSTR)objName.c_str(), fdexNameEnsure, &dispid);
if(FAILED(hRes))
return hRes;
//Step3: method
DISPID namedArgs[] = {DISPID_PROPERTYPUT};
static CComVariant avarParams[1];
//VARIANT avarParams[1];//IE11用这个
DISPPARAMS params;
params.rgvarg = avarParams;
params.rgvarg[0].pdispVal = m_jsObject;
params.rgvarg[0].vt = VT_DISPATCH;
params.rgdispidNamedArgs = namedArgs;
params.cArgs = 1;
params.cNamedArgs = 1;
hRes = pWndEx->InvokeEx(dispid, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT,
¶ms, NULL, NULL, NULL);
if (FAILED(hRes))
return hRes;
return S_OK;
}
第三部份:
#ifndef _JS_LITESTEP_H__
#define _JS_LITESTEP_H__
#include <windows.h>
#include <mshtmhst.h>
#include <string>
#include <map>
/*
Tester:
Kagula@20141118
TestEnvironment:
[1]vs2010SP3 + Win7 64bits
From:
Calling C++ function from JavaScript script running in a web browser control
http://stackoverflow.com/questions/3747414/calling-c-function-from-javascript-script-running-in-a-web-browser-control
*/
class JSObject : public IDispatch {
private:
static const DISPID DISPID_USER_TheFuncNoParam = DISPID_VALUE + 1;
static const DISPID DISPID_USER_TheFuncHave2Params = DISPID_VALUE + 2;
std::map<std::wstring, DISPID> idMap;
long ref;
std::map<std::string, std::string> values;
char *BSTRToLPSTR(BSTR bStr, LPSTR lpstr);
public:
JSObject();
// IUnknown
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv);
virtual ULONG STDMETHODCALLTYPE AddRef();
virtual ULONG STDMETHODCALLTYPE Release();
// IDispatch
virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT *pctinfo);
virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid,
ITypeInfo **ppTInfo);
virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid,
LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId);
virtual HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid,
LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
EXCEPINFO *pExcepInfo, UINT *puArgErr);
};
#endif
#include <utility>
#include <fstream>
#include "jsobject.h"
#include "atlbase.h"
#include <cstring>
JSObject::JSObject() : ref(0)
{
idMap.insert(std::make_pair(L"TheFuncNoParam", DISPID_USER_TheFuncNoParam));
idMap.insert(std::make_pair(L"TheFuncHave2Params", DISPID_USER_TheFuncHave2Params));
}
HRESULT STDMETHODCALLTYPE JSObject::QueryInterface(REFIID riid, void **ppv)
{
*ppv = NULL;
if (riid == IID_IUnknown || riid == IID_IDispatch) {
*ppv = static_cast<IDispatch*>(this);
}
if (*ppv != NULL) {
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
ULONG STDMETHODCALLTYPE JSObject::AddRef()
{
return InterlockedIncrement(&ref);
}
ULONG STDMETHODCALLTYPE JSObject::Release()
{
int tmp = InterlockedDecrement(&ref);
if (tmp == 0) {
OutputDebugString(L"JSObject::Release(): delete this");
delete this;
}
return tmp;
}
HRESULT STDMETHODCALLTYPE JSObject::GetTypeInfoCount(UINT *pctinfo)
{
*pctinfo = 0;
return S_OK;
}
HRESULT STDMETHODCALLTYPE JSObject::GetTypeInfo(UINT iTInfo, LCID lcid,
ITypeInfo **ppTInfo)
{
return E_FAIL;
}
HRESULT STDMETHODCALLTYPE JSObject::GetIDsOfNames(REFIID riid,
LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
{
HRESULT hr = S_OK;
for (UINT i = 0; i < cNames; i++) {
std::map<std::wstring, DISPID>::iterator iter = idMap.find(rgszNames[i]);
if (iter != idMap.end()) {
rgDispId[i] = iter->second;
} else {
rgDispId[i] = DISPID_UNKNOWN;
hr = DISP_E_UNKNOWNNAME;
}
}
return hr;
}
HRESULT STDMETHODCALLTYPE JSObject::Invoke(DISPID dispIdMember, REFIID riid,
LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
if (wFlags & DISPATCH_METHOD) {
HRESULT hr = S_OK;
std::string *args = new std::string[pDispParams->cArgs];
for (size_t i = 0; i < pDispParams->cArgs; ++i) {
BSTR bstrArg = pDispParams->rgvarg[i].bstrVal;
LPSTR arg = NULL;
arg = BSTRToLPSTR(bstrArg, arg);
args[pDispParams->cArgs - 1 - i] = arg; // also re-reverse order of arguments
delete [] arg;
}
switch (dispIdMember) {
case DISPID_USER_TheFuncNoParam: {
//LSExecute(NULL, args[0].c_str(), SW_NORMAL);
MessageBox(NULL,L"DISPID_USER_TheFuncNoParam",L"DISPID_USER_TheFuncNoParam",MB_OK);
break;
}
case DISPID_USER_TheFuncHave2Params: {
std::string strRet;
strRet.append("return string is arg1=");
strRet.append(args[0].c_str());
strRet.append(" arg2=");
strRet.append(args[1].c_str());
char buf[256];
strncpy(buf, strRet.c_str(), sizeof(buf));
int lenW = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, buf, -1, NULL, 0);
BSTR bstrRet = SysAllocStringLen(0, lenW - 1);
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, buf, -1, bstrRet, lenW);
pVarResult->vt = VT_BSTR;
pVarResult->bstrVal = bstrRet;
break;
}
default:
hr = DISP_E_MEMBERNOTFOUND;
}
delete [] args;
return hr;
}
return E_FAIL;
}
char *JSObject::BSTRToLPSTR(BSTR bStr, LPSTR lpstr)
{
int lenW = SysStringLen(bStr);
int lenA = WideCharToMultiByte(CP_ACP, 0, bStr, lenW, 0, 0, NULL, NULL);
if (lenA > 0) {
lpstr = new char[lenA + 1]; // allocate a final null terminator as well
WideCharToMultiByte(CP_ACP, 0, bStr, lenW, lpstr, lenA, NULL, NULL);
lpstr[lenA] = '\0'; // Set the null terminator yourself
} else {
lpstr = NULL;
}
return lpstr;
}