<!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 { CImpIDispatch *m_pDispOM; } // .cpp BOOL CXXXApp::InitInstance() { 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++调用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;
}