Answered BHO IE 9 AddEventListener

  • 05 Maret 2012 17:31
     
      Memiliki Kode

    Hi,

    I'm trying to capture MutationEvent, but I'm failing on obtaining the event target.

    I sucessfuly managed to add the listener

    CComPtr<IDocumentEvent> spIDocumentEvent;
    hr = _spDocument->QueryInterface(IID_IDocumentEvent, reinterpret_cast<void **>(&spIDocumentEvent));	
    if (SUCCEEDED(hr) && spIDocumentEvent)
    {
    	CComPtr<IDOMEvent> spIDOMEvent;
    	BSTR bstrType = _bstr_t("MutationEvent");
    	hr = spIDocumentEvent->createEvent(bstrType, reinterpret_cast<IDOMEvent **>(&spIDOMEvent));
    	if (SUCCEEDED(hr) && spIDOMEvent)
    	{						
    		CComPtr<IDOMMutationEvent> spIDOMMutationEvent;
    		hr = spIDOMEvent->QueryInterface(IID_IDOMMutationEvent, reinterpret_cast<void **>(&spIDOMMutationEvent));	
    		if (SUCCEEDED(hr) && spIDOMMutationEvent)
    		{	
    			CComPtr<IHTMLElement> spIBody;
    			hr = _spDocument->get_body(reinterpret_cast<IHTMLElement **>(&spIBody));
    			if (SUCCEEDED(hr) && spIBody)
    			{
    				BSTR bstrEmpty = _bstr_t("");
    				BSTR bstrValue = _bstr_t("DOMNodeInserted");
    				hr = spIDOMMutationEvent->initMutationEvent(bstrValue, 
    					VARIANT_TRUE,
    					VARIANT_FALSE,
    					spIBody,
    					bstrEmpty,
    					bstrEmpty,
    					bstrEmpty,
    					0);
    
    				if (SUCCEEDED(hr))
    				{
    					CComPtr<IEventTarget> spIEventTarget;
    					hr = spIBody->QueryInterface(IID_IEventTarget, reinterpret_cast<void **>(&spIEventTarget));	
    					if (SUCCEEDED(hr) && spIEventTarget)
    					{
    						_pObjDomMutationEvent = new CIEDOMMutationEvent();
    
    						hr = spIEventTarget->addEventListener(bstrValue, _pObjDomMutationEvent,  VARIANT_TRUE);
    						if (SUCCEEDED(hr))
    						{
    						...
    						}
    					}
    				}
    			}
    		}
    	}
    }

    Now the problem is that on my sink object, the invoke get's called when I insert a node, but I'm unable to obtain the Node that was inserted, I thought that it would be on the disparams, but they are always "empty"

    HRESULT STDMETHODCALLTYPE CIEDOMMutationEvent::Invoke(
    	DISPID dispIdMember,
    	REFIID riid,
    	LCID lcid,
    	WORD wFlags,
    	DISPPARAMS *pDispParams,
    	VARIANT *pVarResult,
    	EXCEPINFO *pExcepInfo,
    	UINT *puArgErr)
    {
    	if(dispIdMember == 0)
    	{
    		
    		if(pDispParams->rgvarg && pDispParams->rgvarg->vt == VT_DISPATCH)
    		{
    			....
    		}
    	}
    	
    	return S_OK;
    }

    Thanks in advance.

Semua Balasan

  • 07 Maret 2012 7:41
    Moderator
     
     

    Hello,

    I think you need to call IDOMMutationEvent::newValue property to get the insert node. Please check this document.
    http://msdn.microsoft.com/en-us/library/ie/ff975906(v=vs.85).aspx

    Best regards,
    Jesse


    Jesse Jiang [MSFT]
    MSDN Community Support | Feedback to us

  • 07 Maret 2012 10:57
     
      Memiliki Kode

    Hi, thanks for your reply.

    Consider this code to Add the Event

    CComPtr<IHTMLElement> spIBody;
    hr = _spDocument->get_body(reinterpret_cast<IHTMLElement **>(&spIBody));
    if (SUCCEEDED(hr) && spIBody)
    {
    	CComPtr<IEventTarget> spIEventTarget;
    	hr = spIBody->QueryInterface(IID_IEventTarget, reinterpret_cast<void **>(&spIEventTarget));	
    	if (SUCCEEDED(hr) && spIEventTarget)
    	{
    		_pObjDomMutationEvent = new CIEDOMMutationEvent(); // This class derives from IDispatch
    
    		hr = spIEventTarget->addEventListener(_bstr_t("DOMNodeInserted"), _pObjDomMutationEvent,  VARIANT_TRUE);
    		if (SUCCEEDED(hr))
    		{
    		...
    		}
    	}
    }

    It sucessfully works and I'm able to capture the event inside the "invoke" method in my class CIEDOMMutationEvent

    HRESULT STDMETHODCALLTYPE CIEDOMMutationEvent::Invoke(
    	DISPID dispIdMember,
    	REFIID riid,
    	LCID lcid,
    	WORD wFlags,
    	DISPPARAMS *pDispParams,
    	VARIANT *pVarResult,
    	EXCEPINFO *pExcepInfo,
    	UINT *puArgErr)
    {
    	if(dispIdMember == 0)
    	{
    		// Event happened
    		...
    	}
    	
    	return S_OK;
    }

    Now my problem is that I have no parameters in the pDispParams, and I believe that according to the msdn I should receive 2 parametes, being one a IDOMEvent.

    Maybe it's my implementation of the IDispatch that's isn't accurate, can you give me a example of a IDispatch that should be used when using the new AddEventListener function.

    Thanks.




  • 08 Maret 2012 15:13
     
     Jawab

    Hi,

    I Managed to solve the problem!

    In case someone needs the info, the problem is that you need to create a sinker that derives from IDispatchEx and not from IDispatch.

    And on the InvokeEx you will receive the IDomEvent on the DISPARAMS.

    Despite this fact you still need to pass on the AddEventListener only IDispatch, otherwise you will have a crash.

    So create your sink (that derives from IDispatchEx), query the sink for IDispatch, pass it to the AddEventListener and start working with IE9 and the new Events.

    I really think that msdn should be more accurate.

    Thanks.

    • Ditandai sebagai Jawaban oleh jaugusto.pt 08 Maret 2012 15:13
    •