脚本调用C++相对比较容易,使用ATL组件只需要抛双接口即可,但在exe里如何做到呢?本文实现了在exe里脚本和C++的相互调用.在EXE里也需要对外抛送一个继承自IDispatch的接口.并需要重载它的所有接口。由于水平有限,所以难免有错。
//
头文件
static const GUID IID_CExternal =
... { 0x52fee9af, 0xb3b3, 0x4756, ...{ 0x80, 0x10, 0xfe, 0xa8, 0xf9, 0xfd, 0xd3, 0x3f } } ;
class CExternal: public IDispatch
... {
public:
CExternal(HWND h);
virtual ~CExternal();
ULONG __stdcall AddRef() ...{ return 1; }
ULONG __stdcall Release() ...{ return 1; }
HRESULT __stdcall QueryInterface(REFIID riid, void FAR* FAR* ppv)
...{
if (ppv == NULL)
return E_POINTER;
*ppv = NULL;
if (InlineIsEqualGUID(riid, IID_IUnknown))
...{
*ppv = static_cast<IUnknown *>(this);
return S_OK;
}
if(InlineIsEqualGUID(riid, IID_IDispatch) )
...{
*ppv = static_cast<IDispatch FAR *>(this);
return S_OK;
}
if(InlineIsEqualGUID(riid, IID_CExternal) )
...{
*ppv = static_cast<CExternal *>(this);
return S_OK;
}
return E_NOINTERFACE;
}
HRESULT __stdcall GetTypeInfoCount(UINT FAR* pctinfo)
...{
if (pctinfo == NULL)
...{
return E_INVALIDARG;
}
// there is only one function
*pctinfo = 1;
return NOERROR;
}
HRESULT __stdcall GetTypeInfo(UINT iTInfo,LCID lcid,ITypeInfo FAR* FAR* ppTInfo)
...{
if (ppTInfo == NULL)
return E_INVALIDARG;
*ppTInfo = NULL;
if (iTInfo != 0)
return DISP_E_BADINDEX;
*ppTInfo = m_typeinfo;
if (m_typeinfo!=NULL)
m_typeinfo->AddRef();
return NOERROR;
}
HRESULT __stdcall GetIDsOfNames(REFIID riid,OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid,DISPID FAR*rgdispid)
...{
if(lstrcmpiW(*rgszNames,L"exec")==0)
...{
*rgdispid=0;
return S_OK;
}
return E_FAIL;
}
HRESULT __stdcall Invoke(DISPID dispidMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS FAR* pdispparams,VARIANT FAR* pvarResult,EXCEPINFO FAR* pexcepinfo,UINT FAR* puArgErr)
...{
if((DISPATCH_PROPERTYGET&wFlags || DISPATCH_METHOD&wFlags)
&& dispidMember==0)
...{
CComBSTR sRet;
exec(pdispparams, &sRet);
if (DISPATCH_PROPERTYGET&wFlags)
...{
pvarResult->vt=VT_BSTR;
pvarResult->bstrVal=sRet.Detach();
}
return S_OK;
}
return E_FAIL;
}
HRESULT __stdcall exec(DISPPARAMS FAR* pdispparams, BSTR *pbstrValue);
private:
HWND m_hWnd;
LPTYPEINFO m_typeinfo;
CString GetVariantStr(VARIANT vVal);
} ;
// 实现的文件
CExternal::CExternal(HWND h)
... {
csDisplayStr = "";
m_typeinfo =NULL;
m_hWnd = h;
// Create an exec function
static PARAMDATA PARAM_VALUE[]=...{...{OLESTR("fnName"),VT_BSTR},...{OLESTR("p1"),VT_BSTR}};
static METHODDATA rgmdataCCalc=...{OLESTR("exec"),PARAM_VALUE,0,0,CC_CDECL,2,DISPATCH_METHOD|DISPATCH_PROPERTYGET,VT_BSTR};
static INTERFACEDATA ifdata=...{&rgmdataCCalc, 1};
HRESULT hres=CreateDispTypeInfo(&ifdata, LOCALE_SYSTEM_DEFAULT, &m_typeinfo);
}
CString CExternal::GetVariantStr(VARIANT vVal)
... {
CString csReVal;
switch (vVal.vt)
...{
case VT_BOOL:
...{
if (vVal.boolVal == VARIANT_TRUE)
...{
return("1");
}
else
...{
return("0");
}
break;
}
case VT_I2:
...{
csReVal.Format("%d",vVal.iVal);
return(csReVal);
}
case VT_I4:
...{
csReVal.Format("%d",vVal.lVal);
return(csReVal);
}
// case VT_R8:
// {
// //csReVal.Format("%f",vVal.dblVal);
// csReVal=vVal.dblVal;
// return(csReVal);
// }
case VT_BSTR:
...{
return(CString(vVal.bstrVal));
}
}
return "";
}
HRESULT __stdcall CExternal::exec(DISPPARAMS FAR * pdispparams, BSTR * pbstrValue) // 脚本的入口点
... {
// no argument return
if (pdispparams->cArgs < 1)
...{
*pbstrValue = bstrRet.Detach();
return S_OK;
}
int args = pdispparams->cArgs;
// C calling convention order of parameters is in reversed
CString action = pdispparams->rgvarg[args-1].bstrVal;
debugIt(" exec***action:%s:%d ",action,args);
if (action == "alert")
...{
CString csMessage;
CString csTitle;
if (args > 1)
...{
csMessage= GetVariantStr(pdispparams->rgvarg[args-2]);
}
if (args > 2)
...{
csTitle = GetVariantStr(pdispparams->rgvarg[args-3]);
}
MessageBox(m_hWnd, LPCSTR(csMessage), LPCSTR(csTitle), MB_OK);
}
//else if(action == "什么")
//{
//}
*pbstrValue=bstrRet.Detach(); // 返回值
return S_OK;
}
CExternal:: ~ CExternal()
... {
if(m_typeinfo) m_typeinfo->Release();
}
static const GUID IID_CExternal =
... { 0x52fee9af, 0xb3b3, 0x4756, ...{ 0x80, 0x10, 0xfe, 0xa8, 0xf9, 0xfd, 0xd3, 0x3f } } ;
class CExternal: public IDispatch
... {
public:
CExternal(HWND h);
virtual ~CExternal();
ULONG __stdcall AddRef() ...{ return 1; }
ULONG __stdcall Release() ...{ return 1; }
HRESULT __stdcall QueryInterface(REFIID riid, void FAR* FAR* ppv)
...{
if (ppv == NULL)
return E_POINTER;
*ppv = NULL;
if (InlineIsEqualGUID(riid, IID_IUnknown))
...{
*ppv = static_cast<IUnknown *>(this);
return S_OK;
}
if(InlineIsEqualGUID(riid, IID_IDispatch) )
...{
*ppv = static_cast<IDispatch FAR *>(this);
return S_OK;
}
if(InlineIsEqualGUID(riid, IID_CExternal) )
...{
*ppv = static_cast<CExternal *>(this);
return S_OK;
}
return E_NOINTERFACE;
}
HRESULT __stdcall GetTypeInfoCount(UINT FAR* pctinfo)
...{
if (pctinfo == NULL)
...{
return E_INVALIDARG;
}
// there is only one function
*pctinfo = 1;
return NOERROR;
}
HRESULT __stdcall GetTypeInfo(UINT iTInfo,LCID lcid,ITypeInfo FAR* FAR* ppTInfo)
...{
if (ppTInfo == NULL)
return E_INVALIDARG;
*ppTInfo = NULL;
if (iTInfo != 0)
return DISP_E_BADINDEX;
*ppTInfo = m_typeinfo;
if (m_typeinfo!=NULL)
m_typeinfo->AddRef();
return NOERROR;
}
HRESULT __stdcall GetIDsOfNames(REFIID riid,OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid,DISPID FAR*rgdispid)
...{
if(lstrcmpiW(*rgszNames,L"exec")==0)
...{
*rgdispid=0;
return S_OK;
}
return E_FAIL;
}
HRESULT __stdcall Invoke(DISPID dispidMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS FAR* pdispparams,VARIANT FAR* pvarResult,EXCEPINFO FAR* pexcepinfo,UINT FAR* puArgErr)
...{
if((DISPATCH_PROPERTYGET&wFlags || DISPATCH_METHOD&wFlags)
&& dispidMember==0)
...{
CComBSTR sRet;
exec(pdispparams, &sRet);
if (DISPATCH_PROPERTYGET&wFlags)
...{
pvarResult->vt=VT_BSTR;
pvarResult->bstrVal=sRet.Detach();
}
return S_OK;
}
return E_FAIL;
}
HRESULT __stdcall exec(DISPPARAMS FAR* pdispparams, BSTR *pbstrValue);
private:
HWND m_hWnd;
LPTYPEINFO m_typeinfo;
CString GetVariantStr(VARIANT vVal);
} ;
// 实现的文件
CExternal::CExternal(HWND h)
... {
csDisplayStr = "";
m_typeinfo =NULL;
m_hWnd = h;
// Create an exec function
static PARAMDATA PARAM_VALUE[]=...{...{OLESTR("fnName"),VT_BSTR},...{OLESTR("p1"),VT_BSTR}};
static METHODDATA rgmdataCCalc=...{OLESTR("exec"),PARAM_VALUE,0,0,CC_CDECL,2,DISPATCH_METHOD|DISPATCH_PROPERTYGET,VT_BSTR};
static INTERFACEDATA ifdata=...{&rgmdataCCalc, 1};
HRESULT hres=CreateDispTypeInfo(&ifdata, LOCALE_SYSTEM_DEFAULT, &m_typeinfo);
}
CString CExternal::GetVariantStr(VARIANT vVal)
... {
CString csReVal;
switch (vVal.vt)
...{
case VT_BOOL:
...{
if (vVal.boolVal == VARIANT_TRUE)
...{
return("1");
}
else
...{
return("0");
}
break;
}
case VT_I2:
...{
csReVal.Format("%d",vVal.iVal);
return(csReVal);
}
case VT_I4:
...{
csReVal.Format("%d",vVal.lVal);
return(csReVal);
}
// case VT_R8:
// {
// //csReVal.Format("%f",vVal.dblVal);
// csReVal=vVal.dblVal;
// return(csReVal);
// }
case VT_BSTR:
...{
return(CString(vVal.bstrVal));
}
}
return "";
}
HRESULT __stdcall CExternal::exec(DISPPARAMS FAR * pdispparams, BSTR * pbstrValue) // 脚本的入口点
... {
// no argument return
if (pdispparams->cArgs < 1)
...{
*pbstrValue = bstrRet.Detach();
return S_OK;
}
int args = pdispparams->cArgs;
// C calling convention order of parameters is in reversed
CString action = pdispparams->rgvarg[args-1].bstrVal;
debugIt(" exec***action:%s:%d ",action,args);
if (action == "alert")
...{
CString csMessage;
CString csTitle;
if (args > 1)
...{
csMessage= GetVariantStr(pdispparams->rgvarg[args-2]);
}
if (args > 2)
...{
csTitle = GetVariantStr(pdispparams->rgvarg[args-3]);
}
MessageBox(m_hWnd, LPCSTR(csMessage), LPCSTR(csTitle), MB_OK);
}
//else if(action == "什么")
//{
//}
*pbstrValue=bstrRet.Detach(); // 返回值
return S_OK;
}
CExternal:: ~ CExternal()
... {
if(m_typeinfo) m_typeinfo->Release();
}
C++调用脚本可以使用下面的代码,此代码是我在网上下载的,具体的来源我已经不记得了,但在网上应该可以找到类似的.原理是用到了WebBrowser2,但是C++和脚本的相互调用都用到了HTML页面,使用HTML页面成了包袱,能否丢掉它,我不知道如何实现,望高手指点.......
//
头文件
#pragma once
#include < atlbase.h >
#include < Mshtml.h >
class CCallScript
... {
public:
CCallScript();
virtual ~CCallScript();
BOOL DocumentSet()...{return(m_bDocumentSet);}
BOOL SetDocument(IDispatch* pDisp);
LPDISPATCH GetHtmlDocument() const;
const CComBSTR GetLastError() const;
BOOL GetScript(CComPtr<IDispatch>& spDisp);
BOOL GetScripts(CComPtr<IHTMLElementCollection>& spColl);
BOOL Run(const CComBSTR strFunc,CComVariant* pVarResult = NULL);
BOOL Run(const CComBSTR strFunc,const CComBSTR strArg1,CComVariant* pVarResult = NULL);
BOOL Run(const CComBSTR strFunc,const CComBSTR strArg1,const CComBSTR strArg2,CComVariant* pVarResult = NULL);
BOOL Run(const CComBSTR strFunc,const CComBSTR strArg1,const CComBSTR strArg2,const CComBSTR strArg3,CComVariant* pVarResult = NULL);
BOOL Run(const CComBSTR strFunc,const CSimpleArray<CComBSTR> & paramArray,CComVariant* pVarResult = NULL);
private:
BOOL m_bDocumentSet;
protected:
void ShowError(CComBSTR lpszText);
protected:
CComPtr<IHTMLDocument2> m_spDoc;
CComBSTR m_strError;
} ;
inline void CCallScript::ShowError(CComBSTR lpszText)
... {
m_strError = "Error: ";
m_strError.Append(lpszText);
}
inline const CComBSTR CCallScript::GetLastError() const
... {
return m_strError;
}
inline LPDISPATCH CCallScript::GetHtmlDocument() const
... {
return m_spDoc;
}
// CPP文件
#include " stdafx.h "
#include " CallScript.h "
#define CHECK_POINTER(p)
ATLASSERT(p != NULL);
if (p == NULL)
... {
ShowError("NULL pointer");
return FALSE;
}
const CComBSTR GetSystemErrorMessage(DWORD dwError)
... {
CComBSTR strError;
LPTSTR lpBuffer;
if(!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, dwError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
(LPTSTR) &lpBuffer, 0, NULL))
...{
strError = "FormatMessage Netive Error" ;
}
else
...{
strError = lpBuffer;
LocalFree(lpBuffer);
}
return strError;
}
CCallScript::CCallScript()
... {
m_bDocumentSet = FALSE;
}
CCallScript:: ~ CCallScript()
... {
}
BOOL CCallScript::SetDocument(IDispatch * pDisp)
... {
CHECK_POINTER(pDisp);
m_spDoc = NULL;
CComPtr<IDispatch> spDisp = pDisp;
HRESULT hr = spDisp->QueryInterface(IID_IHTMLDocument2,(void**)&m_spDoc);
if(FAILED(hr))
...{
ShowError("Failed to get HTML document COM object");
return FALSE;
}
m_bDocumentSet = TRUE;
return TRUE;
}
BOOL CCallScript::GetScript(CComPtr < IDispatch >& spDisp)
... {
CHECK_POINTER(m_spDoc);
HRESULT hr = m_spDoc->get_Script(&spDisp);
ATLASSERT(SUCCEEDED(hr));
return SUCCEEDED(hr);
}
BOOL CCallScript::GetScripts(CComPtr < IHTMLElementCollection >& spColl)
... {
CHECK_POINTER(m_spDoc);
HRESULT hr = m_spDoc->get_scripts(&spColl);
ATLASSERT(SUCCEEDED(hr));
return SUCCEEDED(hr);
}
BOOL CCallScript::Run( const CComBSTR strFunc,CComVariant * pVarResult)
... {
CSimpleArray<CComBSTR> paramArray;
return Run(strFunc,paramArray,pVarResult);
}
BOOL CCallScript::Run( const CComBSTR strFunc, const CComBSTR strArg1,CComVariant * pVarResult)
... {
CSimpleArray<CComBSTR> paramArray;
paramArray.Add((CComBSTR &)strArg1);
return Run(strFunc,paramArray,pVarResult);
}
BOOL CCallScript::Run( const CComBSTR strFunc, const CComBSTR strArg1, const CComBSTR strArg2,CComVariant * pVarResult)
... {
CSimpleArray<CComBSTR> paramArray;
paramArray.Add((CComBSTR &)strArg1);
paramArray.Add((CComBSTR &)strArg2);
return Run(strFunc,paramArray,pVarResult);
}
BOOL CCallScript::Run( const CComBSTR strFunc, const CComBSTR strArg1, const CComBSTR strArg2, const CComBSTR strArg3,CComVariant * pVarResult)
... {
CSimpleArray<CComBSTR> paramArray;
paramArray.Add((CComBSTR &)strArg1);
paramArray.Add((CComBSTR &)strArg2);
paramArray.Add((CComBSTR &)strArg3);
return Run(strFunc,paramArray,pVarResult);
}
BOOL CCallScript::Run( const CComBSTR strFunc, const CSimpleArray < CComBSTR >& paramArray,CComVariant * pVarResult)
... {
CComPtr<IDispatch> spScript;
if(!GetScript(spScript))
...{
ShowError("Cannot GetScript");
return FALSE;
}
CComBSTR bstrMember(strFunc);
DISPID dispid = NULL;
HRESULT hr = spScript->GetIDsOfNames(IID_NULL,&bstrMember,1,
LOCALE_SYSTEM_DEFAULT,&dispid);
if(FAILED(hr))
...{
ShowError(GetSystemErrorMessage(hr));
return FALSE;
}
//const int arraySize = paramArray.GetCount();
const int arraySize = paramArray.GetSize();
DISPPARAMS dispparams;
memset(&dispparams, 0, sizeof dispparams);
dispparams.cArgs = arraySize;
dispparams.rgvarg = new VARIANT[dispparams.cArgs];
//__asm {int 3}
CComBSTR bstr;
for( int i = 0; i < arraySize; i++)
...{
bstr.Empty();
//CComBSTR bstr = paramArray.GetAt(arraySize - 1 - i); // back reading
bstr = paramArray[arraySize - 1 - i]; // back reading
//bstr.CopyTo(&dispparams.rgvarg[i].bstrVal); //memory leak
dispparams.rgvarg[i].bstrVal = bstr.m_str; //also cause problem when paras are more than 1
dispparams.rgvarg[i].vt = VT_BSTR;
}
dispparams.cNamedArgs = 0;
EXCEPINFO excepInfo;
memset(&excepInfo, 0, sizeof excepInfo);
CComVariant vaResult;
UINT nArgErr = (UINT)-1; // initialize to invalid arg
hr = spScript->Invoke(dispid,IID_NULL,0,
DISPATCH_METHOD,&dispparams,&vaResult,&excepInfo,&nArgErr);
/**//// bug fix memory leak code start ///
// for( int j = 0; j < arraySize; j++)
// ::SysFreeString(dispparams.rgvarg[j].bstrVal);
/**//// bug fix memory leak code end ///
delete [] dispparams.rgvarg;
if(FAILED(hr))
...{
ShowError(GetSystemErrorMessage(hr));
return FALSE;
}
if(pVarResult)
...{
*pVarResult = vaResult;
}
return FALSE;
}
#pragma once
#include < atlbase.h >
#include < Mshtml.h >
class CCallScript
... {
public:
CCallScript();
virtual ~CCallScript();
BOOL DocumentSet()...{return(m_bDocumentSet);}
BOOL SetDocument(IDispatch* pDisp);
LPDISPATCH GetHtmlDocument() const;
const CComBSTR GetLastError() const;
BOOL GetScript(CComPtr<IDispatch>& spDisp);
BOOL GetScripts(CComPtr<IHTMLElementCollection>& spColl);
BOOL Run(const CComBSTR strFunc,CComVariant* pVarResult = NULL);
BOOL Run(const CComBSTR strFunc,const CComBSTR strArg1,CComVariant* pVarResult = NULL);
BOOL Run(const CComBSTR strFunc,const CComBSTR strArg1,const CComBSTR strArg2,CComVariant* pVarResult = NULL);
BOOL Run(const CComBSTR strFunc,const CComBSTR strArg1,const CComBSTR strArg2,const CComBSTR strArg3,CComVariant* pVarResult = NULL);
BOOL Run(const CComBSTR strFunc,const CSimpleArray<CComBSTR> & paramArray,CComVariant* pVarResult = NULL);
private:
BOOL m_bDocumentSet;
protected:
void ShowError(CComBSTR lpszText);
protected:
CComPtr<IHTMLDocument2> m_spDoc;
CComBSTR m_strError;
} ;
inline void CCallScript::ShowError(CComBSTR lpszText)
... {
m_strError = "Error: ";
m_strError.Append(lpszText);
}
inline const CComBSTR CCallScript::GetLastError() const
... {
return m_strError;
}
inline LPDISPATCH CCallScript::GetHtmlDocument() const
... {
return m_spDoc;
}
// CPP文件
#include " stdafx.h "
#include " CallScript.h "
#define CHECK_POINTER(p)
ATLASSERT(p != NULL);
if (p == NULL)
... {
ShowError("NULL pointer");
return FALSE;
}
const CComBSTR GetSystemErrorMessage(DWORD dwError)
... {
CComBSTR strError;
LPTSTR lpBuffer;
if(!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, dwError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
(LPTSTR) &lpBuffer, 0, NULL))
...{
strError = "FormatMessage Netive Error" ;
}
else
...{
strError = lpBuffer;
LocalFree(lpBuffer);
}
return strError;
}
CCallScript::CCallScript()
... {
m_bDocumentSet = FALSE;
}
CCallScript:: ~ CCallScript()
... {
}
BOOL CCallScript::SetDocument(IDispatch * pDisp)
... {
CHECK_POINTER(pDisp);
m_spDoc = NULL;
CComPtr<IDispatch> spDisp = pDisp;
HRESULT hr = spDisp->QueryInterface(IID_IHTMLDocument2,(void**)&m_spDoc);
if(FAILED(hr))
...{
ShowError("Failed to get HTML document COM object");
return FALSE;
}
m_bDocumentSet = TRUE;
return TRUE;
}
BOOL CCallScript::GetScript(CComPtr < IDispatch >& spDisp)
... {
CHECK_POINTER(m_spDoc);
HRESULT hr = m_spDoc->get_Script(&spDisp);
ATLASSERT(SUCCEEDED(hr));
return SUCCEEDED(hr);
}
BOOL CCallScript::GetScripts(CComPtr < IHTMLElementCollection >& spColl)
... {
CHECK_POINTER(m_spDoc);
HRESULT hr = m_spDoc->get_scripts(&spColl);
ATLASSERT(SUCCEEDED(hr));
return SUCCEEDED(hr);
}
BOOL CCallScript::Run( const CComBSTR strFunc,CComVariant * pVarResult)
... {
CSimpleArray<CComBSTR> paramArray;
return Run(strFunc,paramArray,pVarResult);
}
BOOL CCallScript::Run( const CComBSTR strFunc, const CComBSTR strArg1,CComVariant * pVarResult)
... {
CSimpleArray<CComBSTR> paramArray;
paramArray.Add((CComBSTR &)strArg1);
return Run(strFunc,paramArray,pVarResult);
}
BOOL CCallScript::Run( const CComBSTR strFunc, const CComBSTR strArg1, const CComBSTR strArg2,CComVariant * pVarResult)
... {
CSimpleArray<CComBSTR> paramArray;
paramArray.Add((CComBSTR &)strArg1);
paramArray.Add((CComBSTR &)strArg2);
return Run(strFunc,paramArray,pVarResult);
}
BOOL CCallScript::Run( const CComBSTR strFunc, const CComBSTR strArg1, const CComBSTR strArg2, const CComBSTR strArg3,CComVariant * pVarResult)
... {
CSimpleArray<CComBSTR> paramArray;
paramArray.Add((CComBSTR &)strArg1);
paramArray.Add((CComBSTR &)strArg2);
paramArray.Add((CComBSTR &)strArg3);
return Run(strFunc,paramArray,pVarResult);
}
BOOL CCallScript::Run( const CComBSTR strFunc, const CSimpleArray < CComBSTR >& paramArray,CComVariant * pVarResult)
... {
CComPtr<IDispatch> spScript;
if(!GetScript(spScript))
...{
ShowError("Cannot GetScript");
return FALSE;
}
CComBSTR bstrMember(strFunc);
DISPID dispid = NULL;
HRESULT hr = spScript->GetIDsOfNames(IID_NULL,&bstrMember,1,
LOCALE_SYSTEM_DEFAULT,&dispid);
if(FAILED(hr))
...{
ShowError(GetSystemErrorMessage(hr));
return FALSE;
}
//const int arraySize = paramArray.GetCount();
const int arraySize = paramArray.GetSize();
DISPPARAMS dispparams;
memset(&dispparams, 0, sizeof dispparams);
dispparams.cArgs = arraySize;
dispparams.rgvarg = new VARIANT[dispparams.cArgs];
//__asm {int 3}
CComBSTR bstr;
for( int i = 0; i < arraySize; i++)
...{
bstr.Empty();
//CComBSTR bstr = paramArray.GetAt(arraySize - 1 - i); // back reading
bstr = paramArray[arraySize - 1 - i]; // back reading
//bstr.CopyTo(&dispparams.rgvarg[i].bstrVal); //memory leak
dispparams.rgvarg[i].bstrVal = bstr.m_str; //also cause problem when paras are more than 1
dispparams.rgvarg[i].vt = VT_BSTR;
}
dispparams.cNamedArgs = 0;
EXCEPINFO excepInfo;
memset(&excepInfo, 0, sizeof excepInfo);
CComVariant vaResult;
UINT nArgErr = (UINT)-1; // initialize to invalid arg
hr = spScript->Invoke(dispid,IID_NULL,0,
DISPATCH_METHOD,&dispparams,&vaResult,&excepInfo,&nArgErr);
/**//// bug fix memory leak code start ///
// for( int j = 0; j < arraySize; j++)
// ::SysFreeString(dispparams.rgvarg[j].bstrVal);
/**//// bug fix memory leak code end ///
delete [] dispparams.rgvarg;
if(FAILED(hr))
...{
ShowError(GetSystemErrorMessage(hr));
return FALSE;
}
if(pVarResult)
...{
*pVarResult = vaResult;
}
return FALSE;
}
这两个文件的使用的方法:
//
Get the browser control.
CAxWindow wnd = GetDlgItem(IDC_EXPLORER); // WebBrowser
wnd.QueryControl( & m_spBrowser );
CComPtr < IAxWinAmbientDispatch > spAmbient;
HRESULT hr = wnd.QueryHost( & spAmbient);
// diable the context menu
// disable the scrollbar
if ( SUCCEEDED(hr) )
... {
spAmbient->put_AllowContextMenu(VARIANT_TRUE);
spAmbient->put_DocHostFlags(docHostUIFlagFLAT_SCROLLBAR);
}
// navigate to the base html
VARIANT flag = ... {0} ;
VARIANT name = ... {0} ;
VARIANT post = ... {0} ;
VARIANT head = ... {0} ;
//
// m_spBrowser->Navigate(_bstr_t(GetFullName("WhizConsoleSlave.html")), &flag, &name, &post, &head);
TCHAR szFileName[MAX_PATH];
::GetModuleFileName(_Module.GetModuleInstance(), szFileName, MAX_PATH);
TCHAR szRes[MAX_PATH + 10 ];
::wsprintf(szRes, _T( " res://%s/%0d " ), szFileName, IDR_HTML);
CComVariant vURL(szRes);
m_spBrowser -> Navigate2( & vURL, & flag, & name, & post, & head); // 显示指定的页面
// Create a wrapper about the external dispatch interface
CComObject < CWrapperDispatch >* spdispWrapper = 0 ;
hr = CComObject < CWrapperDispatch > ::CreateInstance( & spdispWrapper);
if ( FAILED(hr) ) return 0 ;
// Dummy for refcount management
CComPtr < IUnknown > spUnk = spdispWrapper;
// Create the object that will handle the external interface for the
// html file.
pExternal = new CExternal(m_hWnd);
m_oExternal = static_cast < IDispatch *> (pExternal);
// Set the external dispatch interface
spdispWrapper -> SetDispatch(m_oExternal); // 对脚本抛送接口
hr = wnd.SetExternalDispatch(spdispWrapper);
// wnd.SetFocus();
// ******************************************************************
// 调用脚本比较容易
if ( m_CallScript.DocumentSet() == FALSE)
... {
IDispatch* d = NULL;
m_spBrowser->get_Document(&d);
m_CallScript.SetDocument(d);
d->Release();
}
m_CallScript.Run(L " DisplayStr " ); // DisplayStr就是脚本的函数
m_CallScript.Run(L " AddDir " , " a " , " b " ); // AddDir也是脚本的函数,a和b是AddDir的参数.
CAxWindow wnd = GetDlgItem(IDC_EXPLORER); // WebBrowser
wnd.QueryControl( & m_spBrowser );
CComPtr < IAxWinAmbientDispatch > spAmbient;
HRESULT hr = wnd.QueryHost( & spAmbient);
// diable the context menu
// disable the scrollbar
if ( SUCCEEDED(hr) )
... {
spAmbient->put_AllowContextMenu(VARIANT_TRUE);
spAmbient->put_DocHostFlags(docHostUIFlagFLAT_SCROLLBAR);
}
// navigate to the base html
VARIANT flag = ... {0} ;
VARIANT name = ... {0} ;
VARIANT post = ... {0} ;
VARIANT head = ... {0} ;
//
// m_spBrowser->Navigate(_bstr_t(GetFullName("WhizConsoleSlave.html")), &flag, &name, &post, &head);
TCHAR szFileName[MAX_PATH];
::GetModuleFileName(_Module.GetModuleInstance(), szFileName, MAX_PATH);
TCHAR szRes[MAX_PATH + 10 ];
::wsprintf(szRes, _T( " res://%s/%0d " ), szFileName, IDR_HTML);
CComVariant vURL(szRes);
m_spBrowser -> Navigate2( & vURL, & flag, & name, & post, & head); // 显示指定的页面
// Create a wrapper about the external dispatch interface
CComObject < CWrapperDispatch >* spdispWrapper = 0 ;
hr = CComObject < CWrapperDispatch > ::CreateInstance( & spdispWrapper);
if ( FAILED(hr) ) return 0 ;
// Dummy for refcount management
CComPtr < IUnknown > spUnk = spdispWrapper;
// Create the object that will handle the external interface for the
// html file.
pExternal = new CExternal(m_hWnd);
m_oExternal = static_cast < IDispatch *> (pExternal);
// Set the external dispatch interface
spdispWrapper -> SetDispatch(m_oExternal); // 对脚本抛送接口
hr = wnd.SetExternalDispatch(spdispWrapper);
// wnd.SetFocus();
// ******************************************************************
// 调用脚本比较容易
if ( m_CallScript.DocumentSet() == FALSE)
... {
IDispatch* d = NULL;
m_spBrowser->get_Document(&d);
m_CallScript.SetDocument(d);
d->Release();
}
m_CallScript.Run(L " DisplayStr " ); // DisplayStr就是脚本的函数
m_CallScript.Run(L " AddDir " , " a " , " b " ); // AddDir也是脚本的函数,a和b是AddDir的参数.