上次写了WebBrowser这个容器( 详细参看:http://blog.csdn.net/norsd/archive/2008/09/13/2921389.aspx)
今天来说说如何在 WebBrowser的基础上扩展更多的功能.
WebBrowserEx : public WebBrowser ,
public IDocHostUIHandler
1.实现
IDocHostUIHandler接口
WebBrowserEx 继承了WebBrowser ,并且加入了IDocHostUIHandler, 该接口可以个性化WB控件, 同样的必须事先实现IDocHostUIHandle
WebBrowserEx .h 部分
- //IDocHostUIHandler
- virtualHRESULTSTDMETHODCALLTYPEShowContextMenu(
- DWORDdwID,
- POINT*ppt,
- IUnknown*pcmdtReserved,
- IDispatch*pdispReserved);
- virtualHRESULTSTDMETHODCALLTYPEGetHostInfo(
- DOCHOSTUIINFO*pInfo);
- virtualHRESULTSTDMETHODCALLTYPEShowUI(
- DWORDdwID,
- IOleInPlaceActiveObject*pActiveObject,
- IOleCommandTarget*pCommandTarget,
- IOleInPlaceFrame*pFrame,
- IOleInPlaceUIWindow*pDoc);
- virtualHRESULTSTDMETHODCALLTYPEHideUI(void);
- virtualHRESULTSTDMETHODCALLTYPEUpdateUI(void);
- //IOleInPlaceFrame已经包含了这个方法 , IOleInPlaceFrame接口在WebBrowser中实现,所以不必要再次实现
- //virtualHRESULTSTDMETHODCALLTYPEEnableModeless(
- //BOOLfEnable);
- virtualHRESULTSTDMETHODCALLTYPEOnDocWindowActivate(
- BOOLfActivate);
- virtualHRESULTSTDMETHODCALLTYPEOnFrameWindowActivate(
- BOOLfActivate);
- virtualHRESULTSTDMETHODCALLTYPEResizeBorder(
- LPCRECTprcBorder,
- IOleInPlaceUIWindow*pUIWindow,
- BOOLfRameWindow);
- virtualHRESULTSTDMETHODCALLTYPETranslateAccelerator(
- LPMSGlpMsg,
- constGUID*pguidCmdGroup,
- DWORDnCmdID);
- virtualHRESULTSTDMETHODCALLTYPEGetOptionKeyPath(
- LPOLESTR*pchKey,
- DWORDdw);
- virtualHRESULTSTDMETHODCALLTYPEGetDropTarget(
- IDropTarget*pDropTarget,
- IDropTarget**ppDropTarget);
- virtualHRESULTSTDMETHODCALLTYPEGetExternal(
- IDispatch**ppDispatch);
- virtualHRESULTSTDMETHODCALLTYPETranslateUrl(
- DWORDdwTranslate,
- OLECHAR*pchURLIn,
- OLECHAR**ppchURLOut);
- virtualHRESULTSTDMETHODCALLTYPEFilterDataObject(
- IDataObject*pDO,
- IDataObject**ppDORet);
- /*
- =====================
- |IDocHostUIHandler|
- =====================
- */
- HRESULTWebBrowser::ShowContextMenu(
- DWORDdwID,
- POINT*ppt,
- IUnknown*pcmdtReserved,
- IDispatch*pdispReserved){returnE_NOTIMPL;}
- HRESULTWebBrowser::GetHostInfo(
- DOCHOSTUIINFO*pInfo){returnE_NOTIMPL;}
- HRESULTWebBrowser::ShowUI(
- DWORDdwID,
- IOleInPlaceActiveObject*pActiveObject,
- IOleCommandTarget*pCommandTarget,
- IOleInPlaceFrame*pFrame,
- IOleInPlaceUIWindow*pDoc){returnE_NOTIMPL;}
- HRESULTWebBrowser::HideUI(void){returnE_NOTIMPL;}
- HRESULTWebBrowser::UpdateUI(void){returnE_NOTIMPL;}
- //HRESULTWebBrowser::EnableModeless(
- //BOOLfEnable){returnE_NOTIMPL;}
- HRESULTWebBrowser::OnDocWindowActivate(
- BOOLfActivate){returnE_NOTIMPL;}
- HRESULTWebBrowser::OnFrameWindowActivate(
- BOOLfActivate){returnE_NOTIMPL;}
- HRESULTWebBrowser::ResizeBorder(
- LPCRECTprcBorder,
- IOleInPlaceUIWindow*pUIWindow,
- BOOLfRameWindow){returnE_NOTIMPL;}
- HRESULTWebBrowser::TranslateAccelerator(
- LPMSGlpMsg,
- constGUID*pguidCmdGroup,
- DWORDnCmdID){returnE_NOTIMPL;}
- HRESULTWebBrowser::GetOptionKeyPath(
- LPOLESTR*pchKey,
- DWORDdw){returnE_NOTIMPL;}
- HRESULTWebBrowser::GetDropTarget(
- IDropTarget*pDropTarget,
- IDropTarget**ppDropTarget)
- {
- returnE_NOTIMPL;//使用默认拖拽
- //returnS_OK;//自定义拖拽
- }
- HRESULTWebBrowser::GetExternal(IDispatch**ppDispatch)
- {
- returnE_NOTIMPL;
- }
- HRESULTWebBrowser::TranslateUrl(
- DWORDdwTranslate,
- OLECHAR*pchURLIn,
- OLECHAR**ppchURLOut){returnE_NOTIMPL;}
- HRESULTWebBrowser::FilterDataObject(
- IDataObject*pDO,
- IDataObject**ppDORet){returnE_NOTIMPL;}
很多人在那篇提问如何在SDK的模式下支持
IDocHostUIHandler, 我的这篇文章就是一个答案了, 你会慢慢爱上SDK的.
2.拖拽的处理
那篇文章:
http://www.vckbase.com/document/viewdoc/?id=1486中由于是MFC的实现, 对于SDK实现来说缺少了一点东西,
3.处理HTML的众多Event
在MFC的 HTMLDialog 中, 可以实现诸如 MouseMove 之类的消息, 让我们用SDK实现之.
下面实现了一个简单的事件onmousemove
WebBrowserEx.h 部分:
- virtualSTDMETHODIMP_(void)DocumentComplete(IDispatch*pDisp,VARIANT*URL);//其实是:virtualvoid__stdcallDocumentComplete(...)
- void
- WebBrowserEx::DocumentComplete(IDispatch*pDisp,VARIANT*URL)
- {
- // 装载Event响应函数
- IHTMLDocument3*pHtmlDoc3=GetHTMLDocument3();
- BSTRbsMouseMoveEvent=::SysAllocString(L"onmousemove");
- pHtmlDoc3->attachEvent(
- bsMouseMoveEvent,
- CHtmlEvents::CreateEventObject((EVENT_FUNCTION)WebBrowserEx::OnHtmlMouseMove,0,this));
- ::SysFreeString(bsMouseMoveEvent);
- // 注意在卸载的时候要调用detachEvent
- WebBrowser::DocumentComplete( pDisp, URL );// 掉哦那个基类
- return;
- }
其实现类似于MSDN中的相关类.
HtmlEvents.h
- //EVENT_FUNCTION函数指针定义被应用于:CreateEventObject;
- typedefHRESULT(*EVENT_FUNCTION)(LPVOID);
- classCHtmlEvents:
- publicIDispatch
- {
- public:
- CHtmlEvents();
- virtual~CHtmlEvents(void);
- //IUnknownmethods
- virtualSTDMETHODIMPQueryInterface(REFIIDiid,void**ppvObject);
- virtualSTDMETHODIMP_(ULONG)AddRef();
- virtualSTDMETHODIMP_(ULONG)Release();
- //IDispatchMethods
- HRESULT_stdcallGetTypeInfoCount(unsignedint*pctinfo);
- HRESULT_stdcallGetTypeInfo(unsignedintiTInfo,LCIDlcid,ITypeInfoFAR*FAR*ppTInfo);
- HRESULT_stdcallGetIDsOfNames(REFIIDriid,OLECHARFAR*FAR*rgszNames,unsignedintcNames,LCIDlcid,DISPIDFAR*rgDispId);
- HRESULT_stdcallInvoke(DISPIDdispIdMember,REFIIDriid,LCIDlcid,WORDwFlags,DISPPARAMSFAR*pDispParams,VARIANTFAR*pVarResult,EXCEPINFOFAR*pExcepInfo,unsignedintFAR*puArgErr);
- //OtherMethod
- staticLPDISPATCHCreateEventObject(EVENT_FUNCTIONpFunc,DISPIDid,LPVOIDlpUserData);
- private:
- long_lRef;
- EVENT_FUNCTION_fnEvent;
- DISPID_id;
- LPVOID_pUserData;
- };
- #include"HtmlEvents.h"
- //CHtmlEventsclass
- CHtmlEvents::CHtmlEvents()
- {
- }
- CHtmlEvents::~CHtmlEvents()
- {
- }
- /*
- ==================
- |IUnknownmethods|
- ==================
- */
- STDMETHODIMPCHtmlEvents::QueryInterface(REFIIDiid,void**ppvObject)
- {
- if(iid==IID_IUnknown||iid==IID_IDispatch)
- {
- *ppvObject=this;
- AddRef();
- returnS_OK;
- }
- returnE_NOTIMPL;
- }
- STDMETHODIMP_(ULONG)CHtmlEvents::AddRef()
- {
- returnInterlockedIncrement(&_lRef);
- }
- STDMETHODIMP_(ULONG)CHtmlEvents::Release()
- {
- return::InterlockedDecrement(&_lRef);
- }
- /*
- =====================
- |IDispatchMethods|
- =====================
- */
- HRESULT_stdcallCHtmlEvents::GetTypeInfoCount(
- unsignedint*pctinfo)
- {
- returnE_NOTIMPL;
- }
- HRESULT_stdcallCHtmlEvents::GetTypeInfo(
- unsignedintiTInfo,
- LCIDlcid,
- ITypeInfoFAR*FAR*ppTInfo)
- {
- returnE_NOTIMPL;
- }
- HRESULT_stdcallCHtmlEvents::GetIDsOfNames(REFIIDriid,
- OLECHARFAR*FAR*rgszNames,
- unsignedintcNames,
- LCIDlcid,
- DISPIDFAR*rgDispId
- )
- {
- returnE_NOTIMPL;
- }
- HRESULT_stdcallCHtmlEvents::Invoke(
- DISPIDdispIdMember,
- REFIIDriid,
- LCIDlcid,
- WORDwFlags,
- DISPPARAMS*pDispParams,
- VARIANT*pVarResult,
- EXCEPINFO*pExcepInfo,
- unsignedint*puArgErr)
- {
- if(DISPID_VALUE==dispIdMember)
- {
- (_fnEvent)(_pUserData);
- returnS_OK;
- }
- returnE_NOTIMPL;
- }
- //返回一个CHtmlEvents的实例
- //pFunc表示当相关消息发生时,CHtmlEvents的实例调用pFunc这个函数,同时参数是lpUserData,MSDN上有相关实现.
- //他的注销可以通过Detach后delete
- //或者Release()自动销毁,这里我们用了Detach后delete
- LPDISPATCHCHtmlEvents::CreateEventObject(EVENT_FUNCTIONpFunc,DISPIDid,LPVOIDlpUserData)
- {
- CHtmlEvents*npHE=newCHtmlEvents;
- npHE->_fnEvent=pFunc;
- npHE->_id=id;
- npHE->_pUserData=lpUserData;
- returnreinterpret_cast<LPDISPATCH>(npHE);
- };