代码如下所示.在DocumentComplete事件里面,对IHTMLDocument2里面的每一个元素都执行了Advise操作,但是,打开网页(如 www.sina.com.cn )之后,点击一个超链接之后,却得到多次OnClick事件.我百思不得其解,请问一下各位高手,这可能是什么方面的问题,应该如何解决?谢谢. STDMETHODIMP BHO::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, 
                                  DISPPARAMS* pDispParams, VARIANT* pvarResult, 
                                  EXCEPINFO*  pExcepInfo,  UINT* puArgErr) 

    switch( dispidMember ) 
    { 
    case DISPID_HTMLELEMENTEVENTS2_ONCLICK: 
        break;     case DISPID_DOCUMENTCOMPLETE: 
        CComPtr <IDispatch> spDisp; 
        hResult = m_pWebBrowser2->get_Document(&spDisp); 
        if (SUCCEEDED( hResult ) && spDisp) 
        { 
            CComQIPtr <IHTMLDocument2, &IID_IHTMLDocument2> spHTML(spDisp); 
            if ( spHTML ) 
            { 
                IHTMLElementCollection* pElemColl = NULL; 
                if ( SUCCEEDED( spHTML->get_all( &pElemColl ) ) ) 
                { 
                    LONG lItem; 
                    pElemColl->get_length( &lItem ); 
                    for( INT iCount = 0; iCount  < lItem; iCount ++ ) 
                    { 
                        _variant_t index = iCount; 
                        IDispatch * pItemDisp;                         if ( SUCCEEDED( pElemColl->item(index, index, &pItemDisp) ) ) 
                        { 
                            CComPtr <IConnectionPointContainer> pConnPtContainer; 
                            hResult = pItemDisp->QueryInterface(IID_IConnectionPointContainer, (void**)&pConnPtContainer); 
                            if ( SUCCEEDED(hResult) ) 
                            { 
                                CComPtr <IConnectionPoint> spConnPt; 
                                hResult = pConnPtContainer->FindConnectionPoint(DIID_HTMLElementEvents2, &spConnPt); 
                                if (SUCCEEDED(hResult) ) 
                                { 
                                    DWORD newSess; 
                                    hResult = spConnPt->Advise((IDispatch*)this, &newSess); 
                                    if ( SUCCEEDED(hResult) ) 
                                    { 
                                    } 
                                } 
                            } 
                            pItemDisp->Release(); 
                        } 
                    } 
                } 
                pElemColl->Release(); 
            } 
        } 
    default: 
        break; 
    } }

解决方案 »

  1.   

    这是DOM的sinking和bubbling机制在作怪,一个元素事件会从根元素开始往深层sinking,接着又往外层bubbling,除非某个元素事件响应中设置了event.cancelBubble=true才终止bubbling,设置了event.returnValue=true才终止sinking。没必要为每个元素都建立连接点的,对感兴趣的元素接收事件就可以了,而且无需连接点方式,可以用IHTMLElement2::attachEvent来挂接事件响应
      

  2.   

    谢谢楼上的回复.但是,还有一个问题,我已经按你说的调用了put_cancelBubble和put_returnValue,但是,仍然会收到多次DISPID_HTMLELEMENTEVENTS2_ONCLICK事件.请问这是为什么?谢谢.        case DISPID_HTMLELEMENTEVENTS2_ONCLICK:
            {
                IDispatch * pDisp = pDispParams->rgvarg[0].pdispVal;            IHTMLEventObj *pEventObj = NULL;
                hr = pDisp->QueryInterface( IID_IHTMLEventObj, (void **)&pEventObj );
                if ( SUCCEEDED(hr) && pEventObj  )
                {
                    VARIANT varValue;
                    varValue.vt = VT_BOOL;
                    varValue.boolVal = VARIANT_TRUE;                //VARIANT_BOOL bVar;
                    //pEventObj->get_cancelBubble( &bVar );                pEventObj->put_returnValue( varValue );
                    pEventObj->put_cancelBubble( VARIANT_TRUE );                pEventObj->Release();
                }            break;
            }
      

  3.   

    谢谢楼上的回复.按我的理解,对于attachEvent来说,是设置某一个元素的某一个事件(如click事件)到某一个特定的函数里面.对于一个含有非常多元素的网页(如www.sina.com.cn),是不适合的.不知道我的理解是否正确?而我现在需要捕捉的事件是,在某一个网页里面(如www.sina.com.cn),捕捉用户点击了哪个链接.请问一下楼上的高手,我应该怎么做才对?谢谢.
      

  4.   

    只要docment响应点击就可以
    响应的地方有一个参数好像叫EventObj的,得到这个就可以查询的一个IHTMLElement,这个就是你要点击连接
      

  5.   

    IHTMLDocument3::getElementsByTagName --> IHTMLElementCollection
    针对IHTMLElementCollection里面的每一个元素都attachEvent
      

  6.   

    lookvc说的很对,基于DOM的bubble特性,你无需针对所有元素都建立连接点,只需针对根元素IHTMLDocument建立连接就足够了,所有元素的点击事件最终会回到文档的事件中来(某些元素事件处理终止bubble的除外)。
      

  7.   

    谢谢楼上各位的回复.另外,想请问一下各位,某一个网页,通过IE->查看源文件可以得知某图片对应的HTML为: <IMG height="130" src="shang.jpg" width="960">,但是,为什么get_outerHTML返回的却是<IMG height=130 src="shang.jpg" width=960>,从而不能使用LoadXML进行分析了.....再次谢谢