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