Answered BHO IE 9 AddEventListener

  • 2012년 3월 5일 월요일 오후 5:31
     
      코드 있음

    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.

모든 응답

  • 2012년 3월 7일 수요일 오전 7:41
    중재자
     
     

    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

  • 2012년 3월 7일 수요일 오전 10:57
     
      코드 있음

    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.




  • 2012년 3월 8일 목요일 오후 3:13
     
     답변됨

    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.

    • 답변으로 표시됨 jaugusto.pt 2012년 3월 8일 목요일 오후 3:13
    •