IE7实现了多标签(Tab)的特性。我们可以通过target属性指示链接在某个窗口中打开,却无法通过类似的属性指示链接在新的标签中打开。现在我们实现一个行为(Behavior),附加到元素a,从而实现点击链接时自动在新的标签打开。效果如下
- <a style="behavior:url(#default#TabNewDemo);" tabNewActive="true" href="http://www.pimshell.com">test</a>
- tabNewActive:指示新的标签是否激活
也可以这样
- .TabNewDemo{behavior:url(#default#TabNewDemo);}
- <a class="TabNewDemo" href="http://www.pimshell.com">goto my homepage</a>
我们看一下IE是如何处理这个TabNewDemo行为的。
- IE发现元素a附加的行为名称是“#default#TabNewDemo”,default说明这个是已注册的缺省行为。在注册表项HKLM/SOFTWARE/Microsoft/Internet Explorer/Default Behaviors中查找TABNEWDemo对应的行为工厂组件的ClassId。
- 创建行为工厂组件的实例,然后调用行为工厂的方法FindBehavior,从而得到行为的实例。
- 调用行为实例的方法Init,传递环境参数。
- 调用行为实例的方法Notify,在这里行为绑定当前a元素的onclick事件
- 准备就绪。当用户点击a元素时,行为响应onclick事件,通过调用WebBrowser.Navigate2实现在新标签中打开链接
- 页面关闭时,调用行为实例的方法Detach,在这里清理资源。
下面是TabNewDemo行为的实现步骤
第一步:建立一个ATL Com,名称为TabNew,
并在PIMShellDemo.rgs加入如下注册表项
- HKLM
- {
- NoRemove SOFTWARE
- {
- NoRemove Microsoft
- {
- NoRemove 'Internet Explorer'
- {
- NoRemove 'Default Behaviors'
- {
- val TABNEWDemo = s 'CLSID:E785D34B-7C76-4FC2-B6FE-E2A2AABEEDD9'
- }
- }
- }
- }
- }
第二步:继承接口IElementBehaviorFactory,实现方法FindBehavior:
- // IElementBehaviorFactory
- STDMETHODIMP CTabNew::FindBehavior(BSTR bstrBehavior, BSTR bstrBehaviorUrl,
- IElementBehaviorSite* pSite, IElementBehavior** ppBehavior)
- {
- HRESULT hr;
- //check
- if(!CVB::_StrCmpI(bstrBehavior,DF_Behavior_Name))
- return E_FAIL;
- //create
- CComObject<CTabNew>* pTabNew;
- hr=CComObject<CTabNew>::CreateInstance(&pTabNew);
- if(FAILED(hr))
- return hr;
- //ok
- return pTabNew->QueryInterface(IID_IElementBehavior, (void**)ppBehavior);
- }
第三步:继承接口IElementBehavior,实现三个方法:
- // IElementBehavior
- STDMETHODIMP CTabNew::Init(IElementBehaviorSite* pBehaviorSite)
- {
- __SAFECALL_BEGIN;
- // Cache the IElementBehaviorSite interface pointer.
- m_pSite = pBehaviorSite;
- // Cache the IElementBehaviorSiteOM interface pointer.
- m_pOMSite = m_pSite;
- //
- m_pOMSite->RegisterName(DF_Behavior_Name);
- __SAFECALL_END;
- }
- //
- STDMETHODIMP CTabNew::Notify(LONG lEvent, VARIANT* pVar)
- {
- __SAFECALL_BEGIN;
- switch(lEvent)
- {
- case BEHAVIOREVENT_CONTENTREADY:
- //attachevents
- this->__attachEvents(true);
- break;
- }
- __SAFECALL_END;
- }
- //
- STDMETHODIMP CTabNew::Detach()
- {
- __SAFECALL_BEGIN;
- //detach events
- this->__attachEvents(false);
- //
- this->m_pSite=NULL;
- this->m_pOMSite=NULL;
- __SAFECALL_END;
- }
第四步:实现绑定onclick事件的方法__attachEvents
- //
- void CTabNew::__attachEvents(bool bAttach)
- {
- //element
- MSHTML::IHTMLElementPtr pElement=this->m_pSite->GetElement();
- MSHTML::IHTMLElement2Ptr pElement2=pElement;
- //
- if(bAttach)
- {
- //pSystem
- // should install PIMShell (http://www.pimshell.com)
- PIMShellCore::IAjaxSystem_helperPtr pSystem;
- pSystem.CreateInstance(__uuidof(PIMShellCore::CAjaxSystem));
- //this
- IUnknownPtr pThis=this;
- //delegate
- m_pDelegate_onevents=pSystem->CreateDelegateVC1(pThis,(LONGLONG)&Sink_onevents);
- //attach event of onclick
- pElement2->attachEvent(L"onclick",m_pDelegate_onevents);
- }
- else
- {
- if(m_pDelegate_onevents!=NULL)
- {
- //detach event of onclick
- pElement2->detachEvent(L"onclick",m_pDelegate_onevents);
- //
- m_pDelegate_onevents=NULL;
- }
- }
- }
第五步:响应onclick事件
- //
- HRESULT CTabNew::Sink_onevents(VARIANT vEvent,VARIANT vContext,IUnknown* pInstance,VARIANT* pvarResult)
- {
- __SAFECALL_BEGIN;
- //init
- CTabNew* pThis=dynamic_cast<CTabNew*>(pInstance);
- MSHTML::IHTMLEventObjPtr e=vEvent.pdispVal;
- //
- CString sType=e->type;
- //
- if(sType==L"click")
- {
- pThis->__onclick(e);
- }
- __SAFECALL_END;
- }
- //
- void CTabNew::__onclick(const MSHTML::IHTMLEventObjPtr& e)
- {
- //shift or ctrl may by pressed by code.
- VARIANT_BOOL bShift,bCtrl,bAlt;
- bShift=e->shiftKey;
- bCtrl=e->ctrlKey;
- bAlt=e->altKey;
- //if shift or ctrl then return
- if(bShift || bCtrl || bAlt)
- {
- return;
- }
- //element
- MSHTML::IHTMLElementPtr pElement=this->m_pSite->GetElement();
- //pSystem
- // should install PIMShell (http://www.pimshell.com)
- PIMShellCore::IAjaxSystemPtr pSys;
- pSys.CreateInstance(__uuidof(PIMShellCore::CAjaxSystem));
- //tabNewActive href
- bool bTabNewActive=pSys->GetAttribute(pElement,L"tabNewActive",false);
- _bstr_t bstrHref=pSys->GetAttribute(pElement,L"href",L"");
- //webbrowser
- CComPtr<IWebBrowser2> pWebBrowser;
- __CCuteGeneric::__GetWebBrowser(this->m_pOMSite,&pWebBrowser);
- //url
- _variant_t vURL=bstrHref;
- //flag
- LONG nFlags=bTabNewActive?(navOpenInNewTab):(navOpenInBackgroundTab);
- _variant_t vFlag=nFlags;
- //navigate
- pWebBrowser->Navigate2(&vURL,&vFlag,NULL,NULL,NULL);
- //ok
- e->returnValue=false;
- e->cancelBubble=true;
- }
* 源码下载:http://www.pimshell.com/pimshell/downloads/PIMShellDemo.zip
* System绑定元素onclick事件的机制,请参考:http://blog.csdn.net/pimshell/archive/2008/08/05/2773717.aspx