Handling an OnClick event of a checkbox

时光总嘲笑我的痴心妄想 提交于 2019-12-08 02:22:07

问题


I'm trying to handle click events of a checkbox control from a BHO.

Here is my code:

void STDMETHODCALLTYPE CMyBHO::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL)
{
    // ...

    InitPage(pDocument);
}

void CMyBHO::InitPage(IHTMLDocument2 *pDocument)
{
    CComQIPtr<IHTMLDocument3> document3 = pDocument;

    CComPtr<IHTMLElement> elementCheckbox;
    document3->getElementById(CComBSTR(L"checkbox_id_here"), &elementCheckbox);
    if(!elementCheckbox)
        return;

    if(!m_fCheckboxAdvised)
    {
        // Register to sink events from HTMLDocumentEvents2.
        hr = IHTMLElementEvents2Impl::DispEventAdvise(elementCheckbox);
        if(SUCCEEDED(hr))
            m_fCheckboxAdvised = TRUE;
        else
            ATLASSERT(0); // FAILS HERE, hr = 0x80040200
    }
}

Header file:

class ATL_NO_VTABLE CMyBHO :
    /*...*/
    public IDispEventImpl<1, CMyBHO, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1>,
    public IDispEventImpl<2, CMyBHO, &DIID_HTMLElementEvents2, &LIBID_MSHTML, 4, 0>
{
    typedef IDispEventImpl<1, CMyBHO, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1> IDWebBrowserEvents2Impl;
    typedef IDispEventImpl<2, CMyBHO, &DIID_HTMLElementEvents2, &LIBID_MSHTML, 4, 0> IHTMLElementEvents2Impl;

public:

    /*...*/

    BEGIN_SINK_MAP(CMyBHO)
        SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)
        SINK_ENTRY_EX(2, DIID_HTMLElementEvents2, DISPID_HTMLELEMENTEVENTS2_ONCLICK, OnMouseClick)
    END_SINK_MAP()

public:
    STDMETHOD(SetSite)(IUnknown *pUnkSite);

    // DWebBrowserEvents2
    void STDMETHODCALLTYPE OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL);

    // HTMLDocumentEvents2
    void STDMETHODCALLTYPE OnMouseClick(IHTMLEventObj *eventObj);

    /*...*/
};

DispEventAdvise fails with hr = 0x80040200. What am I doing wrong?

Also, when should I call DispEventUnadvise?


回答1:


You don't have the connection point you request, hence the CONNECT_E_NOCONNECTION failure.

Instead of implementing a connection point client for HTML elements with a multitude of interfaces, you might prefer an alternate route and implement IDispatch on your event sink object, and then assign the interface pointer to onclick property of the HTML element. You will get IDispatch::Invoke call on the event.

Here is a code snippet for you for creating an instance of suitable IDispatch implemetnation, and setting onresize property via C++ code:

CComPtr<IHTMLElement> pBodyElementA;
ATLENSURE_SUCCEEDED(pDocument->get_body(&pBodyElementA));
CComPtr<IDispatch> pSinkDispatch;
ATLENSURE_SUCCEEDED(CDispatchEventSink::CreateInstance(&pSinkDispatch));
CComVariant vValue = pSinkDispatch;
ATLENSURE_SUCCEEDED(reinterpret_cast<CComPtr<IDispatch>&>(pBodyElementA).
    PutPropertyByName(L"onresize", &vValue));

CDispatchEventSink class is here, and you will find full sample project there as well (also, SVN link).



来源:https://stackoverflow.com/questions/21089553/handling-an-onclick-event-of-a-checkbox

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