本篇博客旨在说明MFC环境下,使用webbrowser控件 javascript调用C++ 实现流程,这里面涉及到了自动化对象,即IDispatch接口的实现,首先说下大概框架,否则初学者如我看了半天还是不太明白,这些类是如何在一起相互调用 的
现在说下IDispatch接口,该类是ImpDispatch其头文件如下:
#pragma once
class ImpDispatch:public IDispatch
{
public:
ImpDispatch(void);
~ImpDispatch(void);
ULONG m_Ref;
public:
//IUnknown接口的实现
virtual HRESULT STDMETHODCALLTYPE QueryInterface(
/* [in] */ REFIID riid,
/* [iid_is][out] */ __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject)
{
if(riid==IID_IUnknown)
{
*ppvObject=(IUnknown*)this;
return S_OK;
}
else if(riid==IID_IDispatch)
{
*ppvObject=(IDispatch*)this;
return S_OK;
}
return E_FAIL;
}
virtual ULONG STDMETHODCALLTYPE AddRef( void)
{
m_Ref++;
return m_Ref;
}
virtual ULONG STDMETHODCALLTYPE Release( void)
{
m_Ref--;
return m_Ref;
}
//IDispatch接口的实现
virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(
/* [out] */ __RPC__out UINT *pctinfo)
{
return E_FAIL;;
}
virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(
/* [in] */ UINT iTInfo,
/* [in] */ LCID lcid,
/* [out] */ __RPC__deref_out_opt ITypeInfo **ppTInfo)
{
return E_FAIL;
}
virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(
/* [in] */ __RPC__in REFIID riid,
/* [size_is][in] */ __RPC__in_ecount_full(cNames) LPOLESTR *rgszNames,
/* [range][in] */ __RPC__in_range(0,16384) UINT cNames,
/* [in] */ LCID lcid,
/* [size_is][out] */ __RPC__out_ecount_full(cNames) DISPID *rgDispId)
{
rgDispId[0]=100;
return S_OK;
}
virtual /* [local] */ HRESULT STDMETHODCALLTYPE 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)
{
if(dispIdMember==100)
{
MessageBox(NULL,L"这是C++调用的结果",L"提示",0);
}
我们需要注意的是如果是有参数传递的话,加入是两个整数,则应该这样读取!!!!!
int val1=pDispParams->rgvarg[0].intVal;
int val2=pDispParams->rgvarg[1].intVal;
return S_OK;
}
};
当然其cpp文件如下:
#include "StdAfx.h"
#include "ImpDispatch.h"
ImpDispatch::ImpDispatch(void)
{
m_Ref=0;
}
ImpDispatch::~ImpDispatch(void)
{
}
该类暂定为SiteCtrl,其头文件如下
#pragma once
#include
#include"ImpDispatch.h"
class SiteCtrl: public COleControlSite
{
public:
ImpDispatch* pImp;
public:
~SiteCtrl(void);
SiteCtrl(COleControlContainer*pCtrl):COleControlSite(pCtrl)
{
pImp=new ImpDispatch();
}
BEGIN_INTERFACE_PART(DocHostUIHandler,IDocHostUIHandler)
virtual HRESULT STDMETHODCALLTYPE ShowContextMenu(
/* [in] */ DWORD dwID,
/* [in] */ POINT *ppt,
/* [in] */ IUnknown *pcmdtReserved,
/* [in] */ IDispatch *pdispReserved) ;
virtual HRESULT STDMETHODCALLTYPE GetHostInfo(
/* [out][in] */ DOCHOSTUIINFO *pInfo) ;
virtual HRESULT STDMETHODCALLTYPE ShowUI(
/* [in] */ DWORD dwID,
/* [in] */ IOleInPlaceActiveObject *pActiveObject,
/* [in] */ IOleCommandTarget *pCommandTarget,
/* [in] */ IOleInPlaceFrame *pFrame,
/* [in] */ IOleInPlaceUIWindow *pDoc) ;
virtual HRESULT STDMETHODCALLTYPE HideUI( void);
virtual HRESULT STDMETHODCALLTYPE UpdateUI( void);
virtual HRESULT STDMETHODCALLTYPE EnableModeless(
/* [in] */ BOOL fEnable) ;
virtual HRESULT STDMETHODCALLTYPE OnDocWindowActivate(
/* [in] */ BOOL fActivate) ;
virtual HRESULT STDMETHODCALLTYPE OnFrameWindowActivate(
/* [in] */ BOOL fActivate);
virtual HRESULT STDMETHODCALLTYPE ResizeBorder(
/* [in] */ LPCRECT prcBorder,
/* [in] */ IOleInPlaceUIWindow *pUIWindow,
/* [in] */ BOOL fRameWindow);
virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator(
/* [in] */ LPMSG lpMsg,
/* [in] */ const GUID *pguidCmdGroup,
/* [in] */ DWORD nCmdID) ;
virtual HRESULT STDMETHODCALLTYPE GetOptionKeyPath(
/* [annotation][out] */
__out LPOLESTR *pchKey,
/* [in] */ DWORD dw) ;
virtual HRESULT STDMETHODCALLTYPE GetDropTarget(
/* [in] */ IDropTarget *pDropTarget,
/* [out] */ IDropTarget **ppDropTarget);
virtual HRESULT STDMETHODCALLTYPE GetExternal(
/* [out] */ IDispatch **ppDispatch) ;
virtual HRESULT STDMETHODCALLTYPE TranslateUrl(
/* [in] */ DWORD dwTranslate,
/* [annotation][in] */
__in __nullterminated OLECHAR *pchURLIn,
/* [annotation][out] */
__out OLECHAR **ppchURLOut) ;
virtual HRESULT STDMETHODCALLTYPE FilterDataObject(
/* [in] */ IDataObject *pDO,
/* [out] */ IDataObject **ppDORet);
END_INTERFACE_PART(DocHostUIHandler);
DECLARE_INTERFACE_MAP();
};
#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)
{
}
接下来是实现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的书写,如下
现在说下其中使用到的几个红,即 ,比如该类是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则是要实现的接口!