走进PIMShell(3)--实现TabNew行为(Behavior)

IE7实现了多标签(Tab)的特性。我们可以通过target属性指示链接在某个窗口中打开,却无法通过类似的属性指示链接在新的标签中打开。现在我们实现一个行为(Behavior),附加到元素a,从而实现点击链接时自动在新的标签打开。效果如下

  1. <a style="behavior:url(#default#TabNewDemo);" tabNewActive="true" href="http://www.pimshell.com">test</a>
  2. tabNewActive:指示新的标签是否激活

也可以这样

  1. .TabNewDemo{behavior:url(#default#TabNewDemo);}
  2. <a class="TabNewDemo" href="http://www.pimshell.com">goto my homepage</a>

我们看一下IE是如何处理这个TabNewDemo行为的。

  1. IE发现元素a附加的行为名称是“#default#TabNewDemo”,default说明这个是已注册的缺省行为。在注册表项HKLM/SOFTWARE/Microsoft/Internet Explorer/Default Behaviors中查找TABNEWDemo对应的行为工厂组件的ClassId。
  2. 创建行为工厂组件的实例,然后调用行为工厂的方法FindBehavior,从而得到行为的实例。
  3. 调用行为实例的方法Init,传递环境参数。
  4. 调用行为实例的方法Notify,在这里行为绑定当前a元素的onclick事件
  5. 准备就绪。当用户点击a元素时,行为响应onclick事件,通过调用WebBrowser.Navigate2实现在新标签中打开链接
  6. 页面关闭时,调用行为实例的方法Detach,在这里清理资源。

下面是TabNewDemo行为的实现步骤

 

第一步:建立一个ATL Com,名称为TabNew,

并在PIMShellDemo.rgs加入如下注册表项

  1. HKLM
  2. {
  3.     NoRemove SOFTWARE
  4.     {
  5.         NoRemove Microsoft
  6.         {
  7.             NoRemove 'Internet Explorer'
  8.             {   
  9.                 NoRemove 'Default Behaviors'
  10.                 {
  11.                     val TABNEWDemo = s 'CLSID:E785D34B-7C76-4FC2-B6FE-E2A2AABEEDD9'
  12.                 }
  13.             }
  14.         }
  15.     }
  16. }

第二步:继承接口IElementBehaviorFactory,实现方法FindBehavior:

  1. // IElementBehaviorFactory
  2. STDMETHODIMP CTabNew::FindBehavior(BSTR bstrBehavior, BSTR bstrBehaviorUrl,
  3.     IElementBehaviorSite* pSite, IElementBehavior** ppBehavior)
  4. {
  5.     HRESULT hr; 
  6.     
  7.     //check
  8.     if(!CVB::_StrCmpI(bstrBehavior,DF_Behavior_Name))
  9.         return E_FAIL;
  10.     //create
  11.     CComObject<CTabNew>* pTabNew;
  12.     hr=CComObject<CTabNew>::CreateInstance(&pTabNew);
  13.     if(FAILED(hr))
  14.         return hr;
  15.     //ok
  16.     return pTabNew->QueryInterface(IID_IElementBehavior, (void**)ppBehavior);
  17. }

第三步:继承接口IElementBehavior,实现三个方法:

  1. // IElementBehavior
  2. STDMETHODIMP CTabNew::Init(IElementBehaviorSite* pBehaviorSite)
  3. {
  4. __SAFECALL_BEGIN;
  5.     // Cache the IElementBehaviorSite interface pointer.
  6.     m_pSite = pBehaviorSite;
  7.     // Cache the IElementBehaviorSiteOM interface pointer.
  8.     m_pOMSite = m_pSite;
  9.     //
  10.     m_pOMSite->RegisterName(DF_Behavior_Name);
  11. __SAFECALL_END;
  12. }
  13. //
  14. STDMETHODIMP CTabNew::Notify(LONG lEvent, VARIANT* pVar)
  15. {
  16. __SAFECALL_BEGIN;
  17.     switch(lEvent)
  18.     {
  19.     case BEHAVIOREVENT_CONTENTREADY:
  20.         //attachevents
  21.         this->__attachEvents(true);
  22.         break;
  23.     }
  24. __SAFECALL_END;
  25. }
  26. //
  27. STDMETHODIMP CTabNew::Detach()
  28. {
  29. __SAFECALL_BEGIN;
  30.     //detach events
  31.     this->__attachEvents(false);
  32.     //
  33.     this->m_pSite=NULL;
  34.     this->m_pOMSite=NULL;
  35. __SAFECALL_END;
  36. }

第四步:实现绑定onclick事件的方法__attachEvents

  1. //
  2. void CTabNew::__attachEvents(bool bAttach)
  3. {
  4.     //element
  5.     MSHTML::IHTMLElementPtr pElement=this->m_pSite->GetElement();
  6.     MSHTML::IHTMLElement2Ptr pElement2=pElement;
  7.     //
  8.     if(bAttach)
  9.     {
  10.         //pSystem 
  11.         //          should install PIMShell (http://www.pimshell.com)
  12.         PIMShellCore::IAjaxSystem_helperPtr pSystem;
  13.         pSystem.CreateInstance(__uuidof(PIMShellCore::CAjaxSystem));
  14.         //this
  15.         IUnknownPtr pThis=this;
  16.         //delegate
  17.         m_pDelegate_onevents=pSystem->CreateDelegateVC1(pThis,(LONGLONG)&Sink_onevents);
  18.         //attach event of onclick
  19.         pElement2->attachEvent(L"onclick",m_pDelegate_onevents);
  20.     }
  21.     else
  22.     {
  23.         if(m_pDelegate_onevents!=NULL)
  24.         {
  25.             //detach event of onclick
  26.             pElement2->detachEvent(L"onclick",m_pDelegate_onevents);
  27.             //
  28.             m_pDelegate_onevents=NULL;
  29.         }
  30.     }
  31. }

第五步:响应onclick事件

  1. //
  2. HRESULT CTabNew::Sink_onevents(VARIANT vEvent,VARIANT vContext,IUnknown* pInstance,VARIANT* pvarResult)
  3. {
  4. __SAFECALL_BEGIN;
  5.     //init
  6.     CTabNew* pThis=dynamic_cast<CTabNew*>(pInstance);
  7.     MSHTML::IHTMLEventObjPtr e=vEvent.pdispVal;
  8.     //
  9.     CString sType=e->type;
  10.     //
  11.     if(sType==L"click")
  12.     {
  13.         pThis->__onclick(e);
  14.     }
  15. __SAFECALL_END;
  16. }
  17. //
  18. void CTabNew::__onclick(const MSHTML::IHTMLEventObjPtr& e)
  19. {
  20.     //shift or ctrl may by pressed by code.
  21.     VARIANT_BOOL bShift,bCtrl,bAlt;
  22.     
  23.     bShift=e->shiftKey;
  24.     bCtrl=e->ctrlKey;
  25.     bAlt=e->altKey;
  26.     //if shift or ctrl then return
  27.     if(bShift || bCtrl || bAlt)
  28.     {   
  29.         return;
  30.     }
  31.     //element
  32.     MSHTML::IHTMLElementPtr pElement=this->m_pSite->GetElement();
  33.     //pSystem 
  34.     //          should install PIMShell (http://www.pimshell.com)
  35.     PIMShellCore::IAjaxSystemPtr pSys;
  36.     pSys.CreateInstance(__uuidof(PIMShellCore::CAjaxSystem));
  37.     //tabNewActive href
  38.     bool bTabNewActive=pSys->GetAttribute(pElement,L"tabNewActive",false);
  39.     _bstr_t bstrHref=pSys->GetAttribute(pElement,L"href",L"");
  40.     //webbrowser
  41.     CComPtr<IWebBrowser2> pWebBrowser;
  42.     __CCuteGeneric::__GetWebBrowser(this->m_pOMSite,&pWebBrowser);
  43.     //url
  44.     _variant_t vURL=bstrHref;
  45.     //flag
  46.     LONG nFlags=bTabNewActive?(navOpenInNewTab):(navOpenInBackgroundTab);
  47.     _variant_t vFlag=nFlags;
  48.     //navigate
  49.     pWebBrowser->Navigate2(&vURL,&vFlag,NULL,NULL,NULL);
  50.     
  51.     //ok
  52.     e->returnValue=false;
  53.     e->cancelBubble=true;
  54. }

* 源码下载:http://www.pimshell.com/pimshell/downloads/PIMShellDemo.zip

* System绑定元素onclick事件的机制,请参考:http://blog.csdn.net/pimshell/archive/2008/08/05/2773717.aspx

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值