vc++訪問javascript(5)–綁定網頁元素的事件

來源:互聯網
上載者:User
 

在VC++中綁定網頁元素的事件(如onclick),通常會使用HTMLElementEvents2事件介面進行。大致如下:

void   CSomeObject:ConnectElement(IHTMLElement*   pElement)   

{

//取得連接點容器

CComQIPtr<IConnectionPointContainer> pCPC=pElement; 

//尋找連接點

CComPtr<IConnectionPoint> pCP;

pCPC->FindConnectionPoint( DIID_HTMLElementEvents2, &pCP);

//串連事件介面

IUnknownPtr pUnk=this; //由CSomeObject實現HTMLElementEvents2事件介面

DWORD dwCookie;

pCP->Advise( pUnk, &dwCookie);

}

 

而在javascript中使用attachEvent綁定網頁元素事件的方式卻顯得更自然,實現也更直接,我們是否也可以用VC++實現呢?

  1. function fn_onclick()
  2. {
  3.    alert("Hello world!");
  4. }
  5. document.all("button1").attachEvent("onclick",fn_onclick);
  6. document.all("button1").detachEvent("onclick",fn_onclick);

先看看在PIMShell中用VC++是怎樣實現以上功能的。

  1. class ATL_NO_VTABLE CVCEventSinkDemo:
  2.  public IDispatchImpl<IVCEventSinkDemo>
  3. {
  4. public:
  5.  CVCEventSinkDemo()
  6.  {
  7.  }
  8.  DECLARE_PROTECT_FINAL_CONSTRUCT()
  9.  HRESULT FinalConstruct()
  10.  {
  11.   return S_OK;
  12.  }
  13.  void FinalRelease()
  14.  {
  15.  }
  16. private:
  17.    //代理對象
  18.    PIMShellCore::IAjaxDelegatePtr m_pDelegate_onevents;
  19.    //回呼函數
  20.    static HRESULT CALLBACK Sink_onevents( VARIANT vEvent, VARIANT vContext, IUnknown* pInstance, VARIANT* pvarResult);
  21.    //綁定事件或取消綁定
  22.    void __attachEvents(bool bAttach);
  23. };
  24. ////////////////////////////////////////////////////
  25. void CVCEventSinkDemo::__attachEvents(bool bAttach)
  26. {
  27.    if(bAttach)
  28.    {
  29.       //產生一個代理對象,傳入this指標和回呼函數
  30.       IUnknownPtr pThis=this;
  31.       m_pDelegate_onevents = o->Sys2->CreateDelegateVC1( pThis, (LONGLONG)&Sink_onevents);
  32.       //綁定事件
  33.        o->Control->AttachEvent(L"onclick", m_pDelegate_onevents);
  34.    }
  35.    else
  36.    {
  37.       if(m_pDelegate_onevents!=NULL)
  38.       {
  39.          //取消綁定
  40.           o->Control->DetachEvent( L"onclick", m_pDelegate_onevents);
  41.          //
  42.          m_pDelegate_onevents=NULL;
  43.       }
  44.    }
  45. }
  46. //當事件發生時,調用此函數
  47. HRESULT CVCEventSinkDemo::Sink_onevents( VARIANT vEvent, VARIANT vContext, IUnknown* pInstance, VARIANT* pvarResult)
  48. {
  49. __SAFECALL_BEGIN;
  50.  //取得this指標
  51.  CVCEventSinkDemo* pThis=dynamic_cast<CVCEventSinkDemo*>(pInstance);
  52.  //取得event對象
  53.  MSHTML::IHTMLEventObjPtr e=vEvent.pdispVal;
  54.  //event.type
  55.  CString sType=e->type;
  56.  //
  57.  if(sType==L"click")
  58.  {
  59.      //執行響應代碼
  60.  }
  61. __SAFECALL_END;
  62. }

1、先產生一個代理對象,這個對象記錄CVCEventSinkDemo的執行個體指標和回呼函數,與C#中delegate的設計理念一致。

2、將代理對象傳入attachEvent實現對onclick事件的綁定。

3、當事件發生時,系統調用代理對象的0方法,

4、在代理對象的0方法中,調用先前記錄的回呼函數,並將CVCEventSinkDemo的執行個體指標傳入。

 

 

我們接下來看看CreateDelegateVC1是如何組建代理程式對象的。

  1. HRESULT CreateDelegateVC1( IUnknown* pInstance, LONGLONG lnCallback, IDispatch** ppDelegate)
  2. {
  3.    //組建代理程式對象
  4.    CComObject<CVCDelegateDemo>* pDelegate;
  5.    HRESULT hr=CComObject<CVCDelegateDemo>::CreateInstance(&pDelegate);
  6.    if(FAILED(hr))
  7.       return hr;
  8.    //記錄執行個體指標和回呼函數
  9.    pDelegate->__record(pInstance,lnCallback);
  10.    //ok
  11.    return pDelegate->QueryInterface(IID_IDispatch,(void**)ppDelegate);
  12. }

接下來,我們看CVCDelegateDemo的0方法是如何?的

  1. class ATL_NO_VTABLE CVCDelegateDemo:
  2.  public IDispatchImpl<CVCDelegateDemo>
  3. {
  4. public:
  5.  CVCDelegateDemo()
  6.  {
  7.  }
  8.  DECLARE_PROTECT_FINAL_CONSTRUCT()
  9.  HRESULT FinalConstruct()
  10.  {
  11.   return S_OK;
  12.  }
  13.  void FinalRelease()
  14.  {
  15.  }
  16. //聲明回呼函數的格式
  17. typedef HRESULT (CALLBACK* _delegateVC1)( VARIANT vParam1, VARIANT vContext, IUnknown* pInstance, VARIANT* pvarResult);
  18. private:
  19.     IUnknownPtr       m_pInstance;
  20.     _delegateVC1      m_pCallback1;
  21. public:
  22.     
  23.     //record
  24.     void __record(IUnknown* pInstance,LONGLONG lnCallback)
  25.     {
  26.         //記錄執行個體指標和回呼函數
  27.          this->m_pInstance=pInstance;
  28.         this->m_pCallback1=(_delegateVC1)lnCallback;
  29.     }
  30. public:
  31.     //實現0方法,並調用回呼函數
  32.     STDMETHOD(Invoke)( DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags,
  33.                        DISPPARAMS* pDispParams, VARIANT* pvarResult,
  34.                        EXCEPINFO*  pExcepInfo,  UINT* puArgErr)
  35.     {
  36.        //只支援0方法
  37.         if(dispidMember!=0)
  38.           return E_INVALIDARG;
  39.        //如果是通過attachEvent綁定網頁元素的事件,那麼傳入的第一個參數就是event對象
  40.         _variant_t vEvent=pDispParams->rgvarg[0];
  41.       //調用回呼函數,傳入event對象和執行個體指標
  42.        (*m_pCallback1)(vEvent,vtMissing,m_pInstance,pvarResult);
  43.       //ok
  44.       return  S_OK; 
  45.     }
  46. };
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.