Javascript post message event handler in ATL C++ BHO

时光总嘲笑我的痴心妄想 提交于 2019-12-04 13:30:18

If you mean window.postMessage, you'd need to add a listener for message event on DOM window object (window.addEventListener("message")) from your BHO. To get the window object, use IWebBrowser2::get_Document, IHTMLDocument2::get_parentWindow, then query the window for IEventTarget and call addEventListener. Give it an implementation of IDispatch as listener parameter. It will be called back as IDispatch::Invoke(DISPID_VALUE) when a message is posted.

[EDITED] This update is based upon the updated code you posted. I can't tell why IEventTarget is still undefined for you (perhaps, there's a problem with your Visual Studio include path configuration). So, just grab the definitions from here:

MIDL_INTERFACE("305104b9-98b5-11cf-bb82-00aa00bdce0b")
IEventTarget : public IDispatch
{
public:
    virtual /* [id] */ HRESULT STDMETHODCALLTYPE addEventListener( 
        /* [in] */ __RPC__in BSTR type,
        /* [in] */ __RPC__in_opt IDispatch *listener,
        /* [in] */ VARIANT_BOOL useCapture) = 0;

    virtual /* [id] */ HRESULT STDMETHODCALLTYPE removeEventListener( 
        /* [in] */ __RPC__in BSTR type,
        /* [in] */ __RPC__in_opt IDispatch *listener,
        /* [in] */ VARIANT_BOOL useCapture) = 0;

    virtual /* [id] */ HRESULT STDMETHODCALLTYPE dispatchEvent( 
        /* [in] */ __RPC__in_opt IDOMEvent *evt,
        /* [out][retval] */ __RPC__out VARIANT_BOOL *pfResult) = 0;

};

MIDL_INTERFACE("305104ba-98b5-11cf-bb82-00aa00bdce0b")
IDOMEvent : public IDispatch
{
public:
    virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_bubbles( 
        /* [out][retval] */ __RPC__out VARIANT_BOOL *p) = 0;

    virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_cancelable( 
        /* [out][retval] */ __RPC__out VARIANT_BOOL *p) = 0;

    virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_currentTarget( 
        /* [out][retval] */ __RPC__deref_out_opt IEventTarget **p) = 0;

    virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_defaultPrevented( 
        /* [out][retval] */ __RPC__out VARIANT_BOOL *p) = 0;

    virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_eventPhase( 
        /* [out][retval] */ __RPC__out USHORT *p) = 0;

    virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_target( 
        /* [out][retval] */ __RPC__deref_out_opt IEventTarget **p) = 0;

    virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_timeStamp( 
        /* [out][retval] */ __RPC__out ULONGLONG *p) = 0;

    virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_type( 
        /* [out][retval] */ __RPC__deref_out_opt BSTR *p) = 0;

    virtual /* [id] */ HRESULT STDMETHODCALLTYPE initEvent( 
        /* [in] */ __RPC__in BSTR eventType,
        /* [in] */ VARIANT_BOOL canBubble,
        /* [in] */ VARIANT_BOOL cancelable) = 0;

    virtual /* [id] */ HRESULT STDMETHODCALLTYPE preventDefault( void) = 0;

    virtual /* [id] */ HRESULT STDMETHODCALLTYPE stopPropagation( void) = 0;

    virtual /* [id] */ HRESULT STDMETHODCALLTYPE stopImmediatePropagation( void) = 0;

    virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_isTrusted( 
        /* [out][retval] */ __RPC__out VARIANT_BOOL *p) = 0;

    virtual /* [id][propput] */ HRESULT STDMETHODCALLTYPE put_cancelBubble( 
        /* [in] */ VARIANT_BOOL v) = 0;

    virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_cancelBubble( 
        /* [out][retval] */ __RPC__out VARIANT_BOOL *p) = 0;

    virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_srcElement( 
        /* [out][retval] */ __RPC__deref_out_opt IHTMLElement **p) = 0;

};

Next, your CIEUIEventListener doesn't look a like a COM object implementation. I don't see any IUnknown and IDispatch methods, perhaps you just didn't show it. You don't have to derive from IDispatchEx either, IDispatch is enough. I suggest you take the following implementation of DOM event sink as a base, it's self-explanatory:

// Usage:
//
// CComPtr<CEventSink> eventSink;
// CEventSink::Create(pTestScript, &eventSink); // pass eventSink where IDispatch* is expected
//

class CEventSink: 
    public CComObjectRoot,
    public IDispatch
{
protected:
    CTestScript* m_pParent;

    CEventSink() { m_pParent = NULL; }

public:
    BEGIN_COM_MAP(CEventSink)
        COM_INTERFACE_ENTRY(IDispatch)
    END_COM_MAP()

    // create and initialize
    static HRESULT Create(CTestScript* pParent, CEventSink** pp)
    {
        CComObject<CEventSink>* pThis = NULL;
        CComObject<CEventSink>::CreateInstance(&pThis);
        if (!pThis) 
            return E_OUTOFMEMORY;

        pThis->m_pParent = pParent;

        (*pp = pThis)->AddRef();
        return S_OK;
    }

    // IDispatch
    STDMETHODIMP GetTypeInfoCount(UINT* pctinfo)
    {
        return E_NOTIMPL; 
    }

    STDMETHODIMP GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
    {
        return E_NOTIMPL; 
    }

    STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid)
    {
        return DISP_E_UNKNOWNNAME;
    }

    STDMETHODIMP Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr)
    {
        if ( dispidMember == DISPID_VALUE )
        {
            // handle the event
            // for example, call some method on m_pParent
        }
        return DISP_E_MEMBERNOTFOUND;
    }
};

If IEventTarget is not visible, be sure you download the IE9 SDK, as the mshtml header and idl in the windows SDK (7.x) do not have it yet.

IE9 and above SDK

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!