c++与js脚本交互,C++调用JS函数/JS调用C++函数

时间:2021-03-22 22:08:35
<!DOCTYPE html>
<html>
<body> <h1>我的第一段 JavaScript</h1> <p>
JavaScript 能够对事件作出反应。比如对按钮的点击:
</p> <button type="button" onclick="myFunction()">点击这里</button> <script>
function myFunction() { window.navigate('app:command&arg1=1&arg2=2')
}
</script>
</body>
</html>

一、javascript调用c++,方法有两种

方案1:

1.html编写

2.C++的CHtmlView类重写OnBeforeNavigate2函数

void CAddGoogleMap_CHtmlView::OnBeforeNavigate2(LPCTSTR lpszURL, DWORD nFlags, LPCTSTR lpszTargetFrameName, CByteArray& baPostedData, LPCTSTR lpszHeaders, BOOL* pbCancel)
{
// TODO: Add your specialized code here and/or call the base class CString strUrl = lpszURL;
if(strUrl.Left() == _T("app:"))
{
// cancel the common url navigate and call your c++ code here
*pbCancel = TRUE;
MessageBox("调用了C++函数", "来自对话框消息");
// call other c++ function here or parse the argument in the strUrl
} CHtmlView::OnBeforeNavigate2(lpszURL, nFlags, lpszTargetFrameName, baPostedData, lpszHeaders, pbCancel); }

方案2:

1.编写html

<html>

<head>

</head>

<body>

<script language="javascript"> function CallCpp()

{

alert('start to call cpp here');

window.external.JavaScriptCallCpp('This is a test for call C++ in JavaScript');

}

</script>

<input type='button'name="xx3" value=调用c++函数 onclick="CallCpp()" />

</body>

<html>

2.C++代码

CString javaScriptName = _T("JavaScriptCallCpp");

#define DISPID_CallCppFromJs 1

// 实现IDispatch 接口

// .h class CImpIDispatch : public IDispatch {     protected:         ULONG               m_cRef;     public:         CImpIDispatch(void);         ~CImpIDispatch(void);         STDMETHODIMP QueryInterface(REFIID, void **);         STDMETHODIMP_(ULONG) AddRef(void);         STDMETHODIMP_(ULONG) Release(void);         //IDispatch         STDMETHODIMP GetTypeInfoCount(UINT* pctinfo);         STDMETHODIMP GetTypeInfo(/* [in] */ UINT iTInfo,             /* [in] */ LCID lcid,             /* [out] */ ITypeInfo** ppTInfo);         STDMETHODIMP GetIDsOfNames(             /* [in] */ REFIID riid,             /* [size_is][in] */ LPOLESTR *rgszNames,             /* [in] */ UINT cNames,             /* [in] */ LCID lcid,             /* [size_is][out] */ DISPID *rgDispId);         STDMETHODIMP 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); }; // .cpp STDMETHODIMP CImpIDispatch::QueryInterface( REFIID riid, void **ppv ) {     *ppv = NULL;     if ( IID_IDispatch == riid )     {         *ppv = this;     }          if ( NULL != *ppv )     {         ((LPUNKNOWN)*ppv)->AddRef();         return NOERROR;     }     return E_NOINTERFACE; } STDMETHODIMP_(ULONG) CImpIDispatch::AddRef(void) {     return ++m_cRef; } STDMETHODIMP_(ULONG) CImpIDispatch::Release(void) {     return --m_cRef; } //IDispatch STDMETHODIMP CImpIDispatch::GetTypeInfoCount(UINT* /*pctinfo*/) {     return E_NOTIMPL; } STDMETHODIMP CImpIDispatch::GetTypeInfo(             /* [in] */ UINT /*iTInfo*/,             /* [in] */ LCID /*lcid*/,             /* [out] */ ITypeInfo** /*ppTInfo*/) {     return E_NOTIMPL; } STDMETHODIMP CImpIDispatch::GetIDsOfNames(             /* [in] */ REFIID riid,             /* [size_is][in] */ OLECHAR** rgszNames,             /* [in] */ UINT cNames,             /* [in] */ LCID lcid,             /* [size_is][out] */ DISPID* rgDispId) {     HRESULT hr;     UINT    i;     // Assume some degree of success     hr = NOERROR;         for ( i=0; i < cNames; i++) {         CString cszName  = rgszNames[i];                 if (cszName == javaScriptName)         {             rgDispId[i] = DISPID_CallCppFromJs;         }         else {             // One or more are unknown so set the return code accordingly             hr = ResultFromScode(DISP_E_UNKNOWNNAME);             rgDispId[i] = DISPID_UNKNOWN;         }     }     return hr; } STDMETHODIMP CImpIDispatch::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) {     CXXXDlg* pDlg = (CCppCallJsDlg*) AfxGetMainWnd();          if (dispIdMember == DISPID_CallCppFromJs)     {         if (wFlags & DISPATCH_PROPERTYGET)         {             if (pVarResult != NULL)             {                 VariantInit(pVarResult);                 V_VT(pVarResult)=VT_BOOL;                 V_BOOL(pVarResult)=true;             }         }         if (wFlags & DISPATCH_METHOD)         {             CString cszArg1= pDispParams->rgvarg[0].bstrVal;             pDlg->CallByScript(cszArg1);         }     }     return S_OK; }

// 改写COleControlSit

// .h class CCustomControlSite:public COleControlSite { public:     CCustomControlSite(COleControlContainer *pCnt):COleControlSite(pCnt){}      BEGIN_INTERFACE_PART(DocHostShowUI, IDocHostShowUI)         INIT_INTERFACE_PART(CDocHostSite, DocHostShowUI)         STDMETHOD(ShowHelp)(             /* [in ] */    HWND hwnd,             /* [in ] */    LPOLESTR pszHelpFile,             /* [in ] */    UINT uCommand,             /* [in ] */    DWORD dwData,             /* [in ] */    POINT ptMouse,             /* [out] */    IDispatch __RPC_FAR *pDispatchObjectHit);         STDMETHOD(ShowMessage)(             /* [in ] */    HWND hwnd,             /* [in ] */    LPOLESTR lpstrText,             /* [in ] */    LPOLESTR lpstrCaption,             /* [in ] */    DWORD dwType,             /* [in ] */    LPOLESTR lpstrHelpFile,             /* [in ] */    DWORD dwHelpContext,             /* [out] */    LRESULT __RPC_FAR *plResult);     END_INTERFACE_PART(DocHostShowUI) protected:     DECLARE_INTERFACE_MAP(); BEGIN_INTERFACE_PART(DocHostUIHandler, IDocHostUIHandler)     STDMETHOD(ShowContextMenu)(/* [in] */ DWORD dwID,             /* [in] */ POINT __RPC_FAR *ppt,             /* [in] */ IUnknown __RPC_FAR *pcmdtReserved,             /* [in] */ IDispatch __RPC_FAR *pdispReserved);     STDMETHOD(GetHostInfo)(              /* [out][in] */ DOCHOSTUIINFO __RPC_FAR *pInfo);     STDMETHOD(ShowUI)(              /* [in] */ DWORD dwID,             /* [in] */ IOleInPlaceActiveObject __RPC_FAR *pActiveObject,             /* [in] */ IOleCommandTarget __RPC_FAR *pCommandTarget,             /* [in] */ IOleInPlaceFrame __RPC_FAR *pFrame,             /* [in] */ IOleInPlaceUIWindow __RPC_FAR *pDoc);     STDMETHOD(HideUI)(void);     STDMETHOD(UpdateUI)(void);     STDMETHOD(EnableModeless)(/* [in] */ BOOL fEnable);     STDMETHOD(OnDocWindowActivate)(/* [in] */ BOOL fEnable);     STDMETHOD(OnFrameWindowActivate)(/* [in] */ BOOL fEnable);     STDMETHOD(ResizeBorder)(              /* [in] */ LPCRECT prcBorder,             /* [in] */ IOleInPlaceUIWindow __RPC_FAR *pUIWindow,             /* [in] */ BOOL fRameWindow);     STDMETHOD(TranslateAccelerator)(              /* [in] */ LPMSG lpMsg,             /* [in] */ const GUID __RPC_FAR *pguidCmdGroup,             /* [in] */ DWORD nCmdID);     STDMETHOD(GetOptionKeyPath)(              /* [out] */ LPOLESTR __RPC_FAR *pchKey,             /* [in] */ DWORD dw);     STDMETHOD(GetDropTarget)(             /* [in] */ IDropTarget __RPC_FAR *pDropTarget,             /* [out] */ IDropTarget __RPC_FAR *__RPC_FAR *ppDropTarget);     STDMETHOD(GetExternal)(              /* [out] */ IDispatch __RPC_FAR *__RPC_FAR *ppDispatch);     STDMETHOD(TranslateUrl)(              /* [in] */ DWORD dwTranslate,             /* [in] */ OLECHAR __RPC_FAR *pchURLIn,             /* [out] */ OLECHAR __RPC_FAR *__RPC_FAR *ppchURLOut);     STDMETHOD(FilterDataObject)(              /* [in] */ IDataObject __RPC_FAR *pDO,             /* [out] */ IDataObject __RPC_FAR *__RPC_FAR *ppDORet); END_INTERFACE_PART(DocHostUIHandler) }; class CCustomOccManager :public COccManager { public:     CCustomOccManager(){}     COleControlSite* CreateSite(COleControlContainer* pCtrlCont)     {         CCustomControlSite *pSite = new CCustomControlSite(pCtrlCont);         return pSite;     } }; // .cpp BEGIN_INTERFACE_MAP(CCustomControlSite, COleControlSite)     INTERFACE_PART(CCustomControlSite, IID_IDocHostShowUI, DocHostShowUI)     INTERFACE_PART(CCustomControlSite, IID_IDocHostUIHandler, DocHostUIHandler) END_INTERFACE_MAP() ULONG CCustomControlSite::XDocHostShowUI::AddRef() {     METHOD_PROLOGUE(CCustomControlSite, DocHostShowUI);     return pThis->ExternalAddRef(); } ULONG CCustomControlSite::XDocHostShowUI::Release() {     METHOD_PROLOGUE(CCustomControlSite, DocHostShowUI);     return pThis->ExternalRelease(); } HRESULT CCustomControlSite::XDocHostShowUI::QueryInterface(REFIID riid, void ** ppvObj) {     METHOD_PROLOGUE(CCustomControlSite, DocHostShowUI);     return pThis->ExternalQueryInterface( &riid, ppvObj ); } HRESULT CCustomControlSite::XDocHostShowUI::ShowHelp(HWND hwnd,                                                LPOLESTR pszHelpFile,                                                UINT nCommand,                                                DWORD dwData,                                                POINT ptMouse,                                                IDispatch * pDispatchObjectHit) {     METHOD_PROLOGUE(CCustomControlSite, DocHostShowUI);     return S_OK; } HRESULT CCustomControlSite::XDocHostShowUI::ShowMessage(HWND hwnd,                                                   LPOLESTR lpstrText,                                                   LPOLESTR lpstrCaption,                                                   DWORD dwType,                                                   LPOLESTR lpstrHelpFile,                                                   DWORD dwHelpContext,                                                   LRESULT * plResult) {     METHOD_PROLOGUE(CCustomControlSite, DocHostShowUI);          MessageBox(hwnd, (CString)lpstrText, _T("Cpp & JavaScript"), /*dwType*/MB_ICONWARNING);     return S_OK; } ULONG FAR EXPORT  CCustomControlSite::XDocHostUIHandler::AddRef() {     METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)     return pThis->ExternalAddRef(); } ULONG FAR EXPORT  CCustomControlSite::XDocHostUIHandler::Release() {                                 METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)     return pThis->ExternalRelease(); } HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::QueryInterface(REFIID riid, void **ppvObj) {     METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)     HRESULT hr = (HRESULT)pThis->ExternalQueryInterface(&riid, ppvObj);     return hr; } // * CImpIDocHostUIHandler::GetHostInfo // * // * Purpose: Called at initialization // * HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::GetHostInfo( DOCHOSTUIINFO* pInfo ) {     METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)     pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER;     pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;     return S_OK; } // * CImpIDocHostUIHandler::ShowUI // * // * Purpose: Called when MSHTML.DLL shows its UI // * HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::ShowUI(                 DWORD dwID,                  IOleInPlaceActiveObject * /*pActiveObject*/,                 IOleCommandTarget * pCommandTarget,                 IOleInPlaceFrame * /*pFrame*/,                 IOleInPlaceUIWindow * /*pDoc*/) {     METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)     // We've already got our own UI in place so just return S_OK     return S_OK; } // * CImpIDocHostUIHandler::HideUI // * // * Purpose: Called when MSHTML.DLL hides its UI // * HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::HideUI(void) {     METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)     return S_OK; } // * CImpIDocHostUIHandler::UpdateUI // * // * Purpose: Called when MSHTML.DLL updates its UI // * HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::UpdateUI(void) {     METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)     // MFC is pretty good about updating it's UI in it's Idle loop so I don't do anything here     return S_OK; } // * CImpIDocHostUIHandler::EnableModeless // * // * Purpose: Called from MSHTML.DLL's IOleInPlaceActiveObject::EnableModeless // * HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::EnableModeless(BOOL /*fEnable*/) {     METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)     return E_NOTIMPL; } // * CImpIDocHostUIHandler::OnDocWindowActivate // * // * Purpose: Called from MSHTML.DLL's IOleInPlaceActiveObject::OnDocWindowActivate // * HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::OnDocWindowActivate(BOOL /*fActivate*/) {     METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)     return E_NOTIMPL; } // * CImpIDocHostUIHandler::OnFrameWindowActivate // * // * Purpose: Called from MSHTML.DLL's IOleInPlaceActiveObject::OnFrameWindowActivate // * HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::OnFrameWindowActivate(BOOL /*fActivate*/) {     METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)     return E_NOTIMPL; } // * CImpIDocHostUIHandler::ResizeBorder // * // * Purpose: Called from MSHTML.DLL's IOleInPlaceActiveObject::ResizeBorder // * HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::ResizeBorder(                 LPCRECT /*prcBorder*/,                  IOleInPlaceUIWindow* /*pUIWindow*/,                 BOOL /*fRameWindow*/) {     METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)     return E_NOTIMPL; } // * CImpIDocHostUIHandler::ShowContextMenu // * // * Purpose: Called when MSHTML.DLL would normally display its context menu // * HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::ShowContextMenu(                 DWORD /*dwID*/,                  POINT* pptPosition,                 IUnknown* /*pCommandTarget*/,                 IDispatch* /*pDispatchObjectHit*/) {     METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)     return E_NOTIMPL;          //CMenu menu;     //menu.LoadMenu(IDR_CUSTOM_POPUP);     //CMenu* pSubMenu = menu.GetSubMenu(0);     ////Because we passed in theApp.m_pMainWnd all of our     ////WM_COMMAND handlers for the menu items must be handled     ////in CCustomBrowserApp. If you want this to be your dialog     ////you will have to grab a pointer to your dialog class and      ////pass the hWnd of it into the last parameter in this call     //pSubMenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON, pptPosition->x, pptPosition->y, theApp.m_pMainWnd);     return S_OK; // We've shown our own context menu. MSHTML.DLL will no longer try to show its own. } // * CImpIDocHostUIHandler::TranslateAccelerator // * // * Purpose: Called from MSHTML.DLL's TranslateAccelerator routines // * HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::TranslateAccelerator(LPMSG lpMsg,             /* [in] */ const GUID __RPC_FAR *pguidCmdGroup,             /* [in] */ DWORD nCmdID) {     METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)                  //disable F5         if(lpMsg->message == WM_KEYDOWN && GetAsyncKeyState(VK_F5) < 0)             return S_OK;         if(GetKeyState(VK_CONTROL) & 0x8000)         {             //disable ctrl + O             if(lpMsg->message == WM_KEYDOWN && GetAsyncKeyState(0x4F) < 0)                 return S_OK;             //disable ctrl + p             if(lpMsg->message == WM_KEYDOWN && GetAsyncKeyState(0x50) < 0)                 return S_OK;             //disable ctrl + N             if(lpMsg->message == WM_KEYDOWN && GetAsyncKeyState(0x4E) < 0)                 return S_OK;         }         //disable back space         if(lpMsg->wParam == VK_BACK)             return S_OK;     return S_FALSE; } // * CImpIDocHostUIHandler::GetOptionKeyPath // * // * Purpose: Called by MSHTML.DLL to find where the host wishes to store  // *    its options in the registry // * HRESULT FAR EXPORT  CCustomControlSite::XDocHostUIHandler::GetOptionKeyPath(BSTR* pbstrKey, DWORD) {     METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)     return E_NOTIMPL; } STDMETHODIMP CCustomControlSite::XDocHostUIHandler::GetDropTarget(              /* [in] */ IDropTarget __RPC_FAR *pDropTarget,             /* [out] */ IDropTarget __RPC_FAR *__RPC_FAR *ppDropTarget) {     METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)     return E_NOTIMPL; } STDMETHODIMP CCustomControlSite::XDocHostUIHandler::GetExternal(              /* [out] */ IDispatch __RPC_FAR *__RPC_FAR *ppDispatch) {     // return the IDispatch we have for extending the object Model     IDispatch* pDisp = (IDispatch*)theApp.m_pDispOM;     pDisp->AddRef();     *ppDispatch = pDisp;     return S_OK; }          STDMETHODIMP CCustomControlSite::XDocHostUIHandler::TranslateUrl(              /* [in] */ DWORD dwTranslate,             /* [in] */ OLECHAR __RPC_FAR *pchURLIn,             /* [out] */ OLECHAR __RPC_FAR *__RPC_FAR *ppchURLOut) {     METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)     return E_NOTIMPL; }          STDMETHODIMP CCustomControlSite::XDocHostUIHandler::FilterDataObject(              /* [in] */ IDataObject __RPC_FAR *pDO,             /* [out] */ IDataObject __RPC_FAR *__RPC_FAR *ppDORet) {     METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)     return E_NOTIMPL; }

// 修改App

// .h class CImpIDispatch; class CXXXApp : public CWinApp {   c++与js脚本交互,C++调用JS函数/JS调用C++函数   CImpIDispatch    *m_pDispOM;   c++与js脚本交互,C++调用JS函数/JS调用C++函数 } // .cpp BOOL CXXXApp::InitInstance() {    c++与js脚本交互,C++调用JS函数/JS调用C++函数     CWinApp::InitInstance();     CCustomOccManager *pMgr = new CCustomOccManager;     // Create an IDispatch class for extending the Dynamic HTML Object Model      m_pDispOM = new CImpIDispatch;     // Set our control containment up but using our control container      // management class instead of MFC's default     AfxEnableControlContainer(pMgr);    c++与js脚本交互,C++调用JS函数/JS调用C++函数 }

二、C++调用javascript函数

1.编写html,如javascript调用c++的方案1的html

2.c++代码

void CAddGoogleMap_CHtmlView::OnTestSwap() {  // call js function  CComPtr<IDispatch> spScript;  CComPtr<IHTMLDocument2> spDoc;  GetHtmlDocument()->QueryInterface(IID_IHTMLDocument2,(void**)&spDoc);//取得网页文档接口指针  spDoc->get_Script(&spScript);//取得脚本com接口

CComBSTR bstrMember("TestFunc");//javaScript函数名称  DISPID dispid = NULL;  HRESULT hr = spScript->GetIDsOfNames(IID_NULL,&bstrMember,1,            LOCALE_SYSTEM_DEFAULT,&dispid);//取得函数名对应 DISPID  DISPPARAMS dispparams;//根据实际函数情况填写函数参数,这里示例TestFunc函数没有参数据  memset(&dispparams, 0, sizeof dispparams);  dispparams.cArgs = 0;//参数个数  dispparams.rgvarg = new VARIANT[dispparams.cArgs];  dispparams.cNamedArgs = 0;

EXCEPINFO excepInfo;  memset(&excepInfo, 0, sizeof excepInfo);  CComVariant vaResult;  UINT nArgErr = (UINT)-1;  // initialize to invalid arg   //执行JavaScript函数  hr = spScript->Invoke(dispid,IID_NULL,0,        DISPATCH_METHOD,&dispparams,&vaResult,&excepInfo,&nArgErr);

}

转:http://dgj0600.blog.163.com/blog/static/440604322012102325015495/

想要在Javascript中调用C++的方法,只要实现CHtmlView的OnGetExternal方法就可以,OnGetExternal要返回一个IDispatch的指针。关于如何实现取得这个IDispatch我研究了几天,甚至把那本《Com技术内幕》都看了一遍。

我最开始尝试的方法是直接实现一个直接继承于IDispatch的类,实现它的GetIDsOfNames和Invoke等等。不知道这是不是一个最原始的方法了,虽然可以实现,但是实现的过程非常的繁琐,而且在实现Invoke的时候还要处理各种类型的变量问题。

后来尝试的是再建立一个新的atl工程,然后实现一个标准的COM组件,最后在MFC中用标准的COM组件的调用方式来取得一个接口的IDispatch指针。虽然相对上面的这个方法,在需要写的代码量上已经减少了很多了,但要生成一个dll。

最后在网上发现了一个方法,应该算算得上是最简单的方法了吧。通过CCmdTarget实现自动化服务器。

由于CHtmlView也是CCmdTarget的一个子类,所以也可以直接在CHtmlView的派生类上应用这个方法。而我采用的方法是添加一个新的类,假设名为Quote。

1. 在头文件上添加DECLARE_DISPATCH_MAP()。 由于MFC已经生成了一句DECLARE_MESSAGE_MAP(),所以可以添加在DECLARE_MESSAGE_MAP()的后面。

2. 在.CPP文件上添加

BEGIN_DISPATCH_MAP(Quote, CCmdTarget)

END_DISPATCH_MAP()

3. 再添加自己的方法。如Add

int Quote::add(int a, int b)

{

return a+b;

}

4. 在2步骤的两句话中间加入
DISP_FUNCTION(Quote, "add", add, VT_I4, VTS_I4 VTS_I4)
此时2中的结构应该为
BEGIN_DISPATCH_MAP(Quote, CCmdTarget)
DISP_FUNCTION(Quote, "add", add, VT_I4, VTS_I4 VTS_I4)
END_DISPATCH_MAP()
 
5. 在CHtmlView的派生类中添加一个Quote类型的指针,用来保存Quote对象,并在构造函数中为它赋值。
 
6. 重载CHtmlView的OnGetExternal方法,返回pQuote->GetIDispatch(TRUE);
这是GetIDispatch的参数一定是要TRUE。这里的原因我不作深解。
 
这时在Javascript里面调用window.external.add(1, 2);就可以了。
 
VC6下实现相对复杂一些,请看这篇文章 VC6下实现CHtmlView的external的方法
 
转:http://www.zeroplace.cn/article.asp?id=868