Add

IE编程 – Document


定制浏览器
作者:冯明德

浏览器控件是个典型的Active控件,提供了大量的接口及自动化对象,可以灵活的加以控制,需要的时候,可以通过这些接口控制浏览器的行为,或提供相应的出接口定制浏览器。

一、概述
浏览器对象CLSID:
CLSID_WebBrowser

提供的主要接口
IWebBrowser2 浏览器的接口

当文档建立后,可以得到相应的文档接口,文档中各标记元素的接口。
在DHTML中,大量的对象和事件就是又这些接口提供和管理的。

IHTMLDocument2
IHTMLWindow2
IHTMLEventObj
IHTMLElement
….

浏览器还将调用宿主提供的接口,以发出事件或给用户提供定制机会。
出接口
DIID_DWebBrowserEvents2
DIID_HTMLDocumentEvents
DIID_HTMLWindowEvents

(ICustomDoc)
IDocHostUIHandler

二、事件的相应
除了使用MFC缺省的事件响应机制外,也可以自建事件接受器,来响应事件
也就是,在封装对象中提供DIID_DWebBrowserEvents2 接口,然后将此接口作为接受器连接到浏览器对象。

一种做法是
在派生类中,使用MFC建立接口方案提供一个DIID_DWebBrowserEvents2接口对象嵌套成员。

 CFMDBrowser : public CWebBrowser{	...	//事件接收器接口	//DWebBrowserEvents	//这是一个IDispatch分发接口	BEGIN_INTERFACE_PART(BrowserEventSink,DWebBrowserEvents)		STDMETHOD(GetTypeInfoCount)(UINT *pctinfo);			STDMETHOD(GetTypeInfo)(UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo);		STDMETHOD(GetIDsOfNames)(REFIID riid,				LPOLESTR *rgszNames,UINT cNames,				LCID lcid,DISPID *rgDispId);		STDMETHOD(Invoke)(DISPID dispIdMember,REFIID riid,LCID lcid,				WORD wFlags,DISPPARAMS *pDispParams,				VARIANT *pVarResult,EXCEPINFO *pExcepInfo,				UINT  *puArgErr);		END_INTERFACE_PART(BrowserEventSink)	DWORD m_dwEventSinkCookie;	...}

这是一个接收器接口,无需添入到对象的接口表中。
(无需:BEGIN_INTERFACE_MAP、END_INTERFACE_MAP)

这是一个以分发接口(IDispatch)作为出接口的典型例子。在接口函数的实现中。Invoke负责又分发ID调用不同的虚拟函数。(事件函数作为虚拟函数,供派生类重载)

STDMETHODIMP CFMDBrowser::XBrowserEventSink::Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,				  WORD wFlags,DISPPARAMS *pDispParams,				  VARIANT *pVarResult,EXCEPINFO *pExcepInfo,				  UINT  *puArgErr){	METHOD_PROLOGUE(CFMDBrowser,BrowserEventSink)	//将事件分发到各虚拟函数	//分发ID的定义见 exdispid.h	switch(dispIdMember)	{	case DISPID_BEFORENAVIGATE:		...		HRESULT hr=pThis->OnBeforeNavigate(..) //事件对应的虚拟函数		...		break;        case DISPID_NAVIGATECOMPLETE:        		...	case ...	case ...}

建立与浏览器的连接
得到IConnectionPointContainer接口,查找与DIID_DWebBrowserEvents对应的接收器,建立连接,记录连接的标号(m_dwEventSinkCookie);

BOOL CFMDBrowser::Connect(){	IUnknown *p_Unk=GetControlUnknown();	if(p_Unk==NULL)		return FALSE;	BOOL bOK=FALSE;	//查找连接点对象	IConnectionPointContainer *i_cpc=0;	HRESULT hr=p_Unk->QueryInterface(IID_IConnectionPointContainer,		(void **)(&i_cpc));	if (SUCCEEDED(hr))	{		IConnectionPoint *i_cp=0;		hr=i_cpc->FindConnectionPoint(DIID_DWebBrowserEvents,&i_cp);		if (SUCCEEDED(hr))		{			hr=i_cp->Advise(&m_xBrowserEventSink,&m_dwEventSinkCookie);			i_cp->Release();			bOK=TRUE;		}		i_cpc->Release();	}		return bOK;}

结束时,断开与浏览器的连接

BOOL CFMDBrowser::DisConnect(){	IUnknown *p_Unk=GetControlUnknown();	if(p_Unk==NULL)		return FALSE;		BOOL bOK=FALSE;		//查找连接点对象	IConnectionPointContainer *i_cpc=0;	HRESULT hr=p_Unk->QueryInterface(IID_IConnectionPointContainer,		(void **)(&i_cpc));	if (SUCCEEDED(hr))	{		IConnectionPoint *i_cp=0;		hr=i_cpc->FindConnectionPoint(DIID_DWebBrowserEvents,&i_cp);		if (SUCCEEDED(hr))		{			hr=i_cp->Unadvise(m_dwEventSinkCookie);			i_cp->Release();			bOK=TRUE;		}		i_cpc->Release();	}		return bOK;}

三、定制浏览器UI
浏览器提供了IDocHostUIHandler出接口,向用户查询界面特性
可以提供这个接口,与浏览器连接上,在其实现中,定制界面

1.建立接口

class CFMDBrowser : public CWebBrowser{	...	//IDocHostUIHandler接口,控制浏览器界面	BEGIN_INTERFACE_PART(UIHandlerSink,IDocHostUIHandler)		STDMETHOD(ShowContextMenu)(DWORD,POINT*,IUnknown*,IDispatch*);		STDMETHOD(GetHostInfo)(DOCHOSTUIINFO*);		STDMETHOD(ShowUI)(DWORD,			IOleInPlaceActiveObject*,			IOleCommandTarget*,			IOleInPlaceFrame*,			IOleInPlaceUIWindow*);		STDMETHOD(HideUI)();		STDMETHOD(UpdateUI)();		STDMETHOD(EnableModeless)(INT);		STDMETHOD(OnDocWindowActivate)(INT);		STDMETHOD(OnFrameWindowActivate)(INT);		STDMETHOD(ResizeBorder)(LPCRECT,IOleInPlaceUIWindow*,INT);		STDMETHOD(TranslateAccelerator)(LPMSG,const GUID*,DWORD);		STDMETHOD(GetOptionKeyPath)(LPOLESTR*,DWORD);		STDMETHOD(GetDropTarget)(IDropTarget*,IDropTarget**);		STDMETHOD(GetExternal)(IDispatch**);		STDMETHOD(TranslateUrl)(DWORD,OLECHAR*,OLECHAR**);		STDMETHOD(FilterDataObject)(IDataObject*,IDataObject**);	END_INTERFACE_PART(UIHandlerSink)	...}

无需添加接口映射

2.连接到浏览器
需要在NavigateComplete时间发生后,得到
ICustomDoc接口,由此接口的
SetUIHandler成员设置UI接口。

//设置界面接口IDispatch *i_dispatch=0;if (SUCCEEDED(i_dispatch=pThis->GetDocument())){	IHTMLDocument2 *i_htmldoc2=0;	if (SUCCEEDED(i_dispatch->QueryInterface(IID_IHTMLDocument2,			(void **)(&i_htmldoc2))))	{			// force connection of IDocHostUIHandler			ICustomDoc *i_customdoc=0;			if (SUCCEEDED(i_htmldoc2->QueryInterface(						IID_ICustomDoc,						(void **)(&i_customdoc))))			{				i_customdoc->SetUIHandler(					&(pThis->m_xUIHandlerSink));				i_customdoc->Release();			}	}	i_dispatch->Release();}

3.在接口的实现中,控制用户界面
例如更改右键菜单
在STDMETHOD(ShowContextMenu)(DWORD,POINT*,IUnknown*,IDispatch*);
的实现中:

HRESULT CFMDBrowser::ShowContextMenu(DWORD,POINT*,IUnknown*,IDispatch*){	..建立自己的菜单        return S_OK;         }

Random Posts Recent Comments

  • 女友糖尿病害我蛀牙 Says:

    汗一个…...

  • Htj06 Says:

    zhenyouchuangyi...

  • 电商圈 Says:

    试图该怎么建立啊,,怎在程序中是吸纳...

  • edward Says:

    看得人心旷神怡,好文,情不自禁的顶一下...

  • Daniel Says:

    我也在处理这个问题,没有找到好的方法。我用了楼上兄弟的方法,还是可以的。不知道您找到好的方法了吗、我暂时楼上兄弟的方法。...

  • 卡,卡 Says:

    弱弱问一句:博主,你博客的模板这样设计pv高吗?...

  • 站长工具 Says:

    博主,兔年快乐!...

  • health Says:

    great post!!I hope I can read more in your website....

  • pdu Says:

    好博文,支持分享...

  • 站长工具 Says:

    博主的文章很不错,我是站长工具-站长精灵的作者,一款专业的SEO工具软件(可以帮您提高博客的流量),想跟您交换个链接,不知可否...

Tag Cloud

arm audio blog brew cache class debug flash google html j2me java javascript Joke linux lua mobile mtk php python ror ruby server shell stream unix web windows 优化 动态加载 女人 女生 平台 开发 手机 技术 流媒体 测试 漫画 生活 男人 男生 缓存 芯片