VS2010 WEBBROWSER控件探索(二)

     本篇博客旨在说明MFC环境下,使用webbrowser控件 javascript调用C++ 实现流程,这里面涉及到了自动化对象,即IDispatch接口的实现,首先说下大概框架,否则初学者如我看了半天还是不太明白,这些类是如何在一起相互调用 的

VS2010 WEBBROWSER控件探索(二)_第1张图片

现在说下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)
{
}

接下来是与站点建立连接的类,即继承COleControlSite,实现GetExternal,从而与IDispatch建立连接

该类暂定为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)
{
}

获得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的书写,如下












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则是要实现的接口!

你可能感兴趣的:(MFC,webbrowser)