其源文件如下:
#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则是要实现的接口!