其源文件如下:
#include "StdAfx.h" #include "SiteCtrl.h" #include"Custom.h" BEGIN_INTERFACE_MAP(SiteCtrl,COleControlSite) INTERFACE_PART(SiteCtrl,IID_IDocHostUIHandler,DocHostUIHandler) END_INTERFACE_MAP() ULONG SiteCtrl::XDocHostUIHandler::AddRef() { METHOD_PROLOGUE(SiteCtrl, DocHostUIHandler) return pThis->ExternalAddRef(); } ULONG SiteCtrl::XDocHostUIHandler::Release() { METHOD_PROLOGUE(SiteCtrl, DocHostUIHandler) return pThis->ExternalRelease(); } HRESULT SiteCtrl::XDocHostUIHandler::QueryInterface(REFIID riid, void** ppvObj) { METHOD_PROLOGUE(SiteCtrl, DocHostUIHandler) HRESULT hr = (HRESULT)pThis->ExternalQueryInterface(&riid, ppvObj); return hr; } HRESULT SiteCtrl::XDocHostUIHandler::GetHostInfo(DOCHOSTUIINFO* pInfo) { METHOD_PROLOGUE(SiteCtrl, DocHostUIHandler) pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER; pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT; return S_OK; } HRESULT SiteCtrl::XDocHostUIHandler::ShowUI( DWORD dwID, IOleInPlaceActiveObject* /*pActiveObject*/, IOleCommandTarget* pCommandTarget, IOleInPlaceFrame* /*pFrame*/, IOleInPlaceUIWindow* /*pDoc*/) { METHOD_PROLOGUE(SiteCtrl, DocHostUIHandler) return S_OK; } HRESULT SiteCtrl::XDocHostUIHandler::HideUI(void) { METHOD_PROLOGUE(SiteCtrl, DocHostUIHandler) return S_OK; } HRESULT SiteCtrl::XDocHostUIHandler::UpdateUI(void) { METHOD_PROLOGUE(SiteCtrl, DocHostUIHandler) return S_OK; } HRESULT SiteCtrl::XDocHostUIHandler::EnableModeless(BOOL /*fEnable*/) { METHOD_PROLOGUE(SiteCtrl, DocHostUIHandler) return E_NOTIMPL; } HRESULT SiteCtrl::XDocHostUIHandler::OnDocWindowActivate(BOOL /*fActivate*/) { METHOD_PROLOGUE(SiteCtrl, DocHostUIHandler) return E_NOTIMPL; } HRESULT SiteCtrl::XDocHostUIHandler::OnFrameWindowActivate(BOOL /*fActivate*/) { METHOD_PROLOGUE(SiteCtrl, DocHostUIHandler) return E_NOTIMPL; } HRESULT SiteCtrl::XDocHostUIHandler::ResizeBorder( LPCRECT /*prcBorder*/, IOleInPlaceUIWindow* /*pUIWindow*/, BOOL /*fRameWindow*/) { METHOD_PROLOGUE(SiteCtrl, DocHostUIHandler) return E_NOTIMPL; } HRESULT SiteCtrl::XDocHostUIHandler::ShowContextMenu( DWORD /*dwID*/, POINT* pptPosition, IUnknown* /*pCommandTarget*/, IDispatch* /*pDispatchObjectHit*/) { METHOD_PROLOGUE(SiteCtrl, DocHostUIHandler) return S_OK; // We've shown our own context menu. MSHTML.DLL will no longer try to show its own. } HRESULT SiteCtrl::XDocHostUIHandler::TranslateAccelerator( /* [in] */ LPMSG lpMsg, /* [in] */ const GUID __RPC_FAR* pguidCmdGroup, /* [in] */ DWORD nCmdID) { METHOD_PROLOGUE(SiteCtrl, 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; } HRESULT SiteCtrl::XDocHostUIHandler::GetOptionKeyPath(BSTR* pbstrKey, DWORD) { METHOD_PROLOGUE(SiteCtrl, DocHostUIHandler) return E_NOTIMPL; } STDMETHODIMP SiteCtrl::XDocHostUIHandler::GetDropTarget( /* [in] */ IDropTarget __RPC_FAR* pDropTarget, /* [out] */ IDropTarget __RPC_FAR*__RPC_FAR* ppDropTarget) { METHOD_PROLOGUE(SiteCtrl, DocHostUIHandler) return E_NOTIMPL; } STDMETHODIMP SiteCtrl::XDocHostUIHandler::GetExternal( /* [out] */ IDispatch __RPC_FAR*__RPC_FAR* ppDispatch) { // return the IDispatch we have for extending the object Model *ppDispatch=theApp.pImp; return S_OK; } STDMETHODIMP SiteCtrl::XDocHostUIHandler::TranslateUrl( /* [in] */ DWORD dwTranslate, /* [in] */ OLECHAR __RPC_FAR *pchURLIn, /* [out] */ OLECHAR __RPC_FAR*__RPC_FAR* ppchURLOut) { METHOD_PROLOGUE(SiteCtrl, DocHostUIHandler) return E_NOTIMPL; } STDMETHODIMP SiteCtrl::XDocHostUIHandler::FilterDataObject( /* [in] */ IDataObject __RPC_FAR* pDO, /* [out] */ IDataObject __RPC_FAR*__RPC_FAR* ppDORet) { METHOD_PROLOGUE(SiteCtrl, DocHostUIHandler) return E_NOTIMPL; } SiteCtrl::~SiteCtrl(void) { }
获得IDispatch接口,在这里我们只实现GetExternal,获得了IDispatch接口,如函数中theApp是应用程序的句柄,而pImp则是实现IDispatch类的指针。
接下来是实现COccManager接口,方便我们进行实现AfxEnableControlContainer函数的参数:
class CSiteManager : public COccManager { public: CSiteManager(){} COleControlSite* CreateSite(COleControlContainer* pCtrlCont) { SiteCtrl*pSite = NULL; pSite = new SiteCtrl(pCtrlCont); return pSite; } };
最后一步,或者说是倒数第二步,进行控制权的注册,
如上一篇博客那样,添加的webbrowser类中自动生成的类,中添加构造函数:
CExplorer2() { pSiteMag=new CSiteManager(); ::AfxEnableControlContainer(pSiteMag); }
万里长征只剩下最后一步了,就是html的书写,如下 :
<HTML> <HEAD> <META NAME="GENERATOR" Content="Microsoft Visual Studio 8.0"> <TITLE></TITLE> </HEAD> <script type="text/javascript"> function Test() { window.external.TEST(); } </script> <BODY> <input type="button" value="测试" onclick="Test();" /> </BODY> </HTML>
PS:到这里,网页调用C++函数就已经实现了,webbrowser是基于IE内核的,如果,我们使用webbrowser控件浏览网页,同时使用window.eternal,如果没有建立连接的话,则会出现 对象不支持此属性或方法,还有就是,该过程是无参数传递的,具有参数的传递过程,待续...
现在说下其中使用到的几个红,即 ,比如该类是A的话,那么,想要在类外进行函数定义的话,则要使用
A::XlocalClass::Method()
需要在该localClass之前加上X,进行定义
BEGIN_INTERFACE_PART(localClass,Iinterface) END_INTERFACE_PART(localClass)
其中localClass可以认为是内嵌类,而Iinterface则是要实现的接口,在BEGIN_INTERFACE_PART和END_INTERFACE_PART之间则是该接口要实现的所有成员函数
DECLARE_INTERFACE_MAP()则是宏声明,其主要用于基类当中,而要使用
BEGIN_INTERFACE_MAP(theClass,theBase) INTERFACE_PART(theClass,IID,localClass) END_INTERFACE_MAP()
我们可以这样认为theClass是外部类,localClass是局部类,IID则是要实现的接口!