.........
.........CComPtr <AboutWebEvent> pAboutWebEvent;//"AboutWebEvent"是一个从IDispatch派生的类接口,作为新的接口for( long i=0;i<nFormCount;i++ )
{
IDispatch *pDisp = NULL; //取得第 i 项表单  
hr = spElementCollection->item( CComVariant( i ), CComVariant(), &pDisp );  if ( FAILED( hr ) ) continue;  CComQIPtr < IHTMLFormElement > spFormElement = pDisp;  
pDisp->Release();  CComVariant vEvent;
vEvent.pdispVal = ( IDispatch* )pAboutWebEvent; 
vEvent.vt = VT_DISPATCH;
IConnectionPointContainer* pCPC = NULL;
IConnectionPoint* pCP = NULL;
DWORD pdwCookie;
hr=spFormElement->QueryInterface( IID_IConnectionPointContainer,(void**)&pCPC );
if ( hr == S_OK )
{
          hr = pCPC->FindConnectionPoint(DIID_HTMLFormElementEvents2,&pCP);
          if ( hr == S_OK )
          {
                   hr = pCP->Advise((IUnknown*)&vEvent,&pdwCookie);
          }
          pCPC->Release();
}
}
其中的AboutWebEvent是一个从IDispatch派生的类接口,作为新的接口。如下:
class AboutWebEvent : public IDispatch
{
public:
AboutWebEvent():m_dwRef(1)
{};
public:
~AboutWebEvent(){};  DWORD m_dwRef;
// IUnknown
  STDMETHOD(QueryInterface)(const struct _GUID &riid,void ** ppv){
  *ppv = NULL;  if (IID_IUnknown == riid)
  {
  *ppv = (LPUNKNOWN)this;
  AddRef();
  return NOERROR;
  }
  else if (IID_IDispatch == riid)
  {
  *ppv = (IDispatch*)this;
  AddRef();
  return NOERROR;
  }
  else
  {
  return E_NOTIMPL;
  }
  }
  ULONG __stdcall AddRef(void){
  return ++m_dwRef;
  }
  ULONG __stdcall Release(void){
  if (--m_dwRef == 0)  
  {  
  delete this;  
  return 0;  
  }
  return m_dwRef;
  }
// IDispatch
  STDMETHOD(GetTypeInfoCount)(unsigned int *){
  TRACE("GetTypeInfoCount\n"); return E_NOTIMPL;
  }
  STDMETHOD(GetTypeInfo)(unsigned int,unsigned long,struct ITypeInfo ** ){
  TRACE("GetTypeInfo\n"); return E_NOTIMPL;
  }
  STDMETHOD(GetIDsOfNames)(const IID &,LPOLESTR *,UINT,LCID,DISPID *){
  TRACE("GetIDsOfNames\n"); return E_NOTIMPL;
  }
  STDMETHOD(Invoke)(DISPID dispID,const struct _GUID &,unsigned long,unsigned short,struct tagDISPPARAMS * pParams,struct tagVARIANT *,struct tagEXCEPINFO *,unsigned int *)
  {
switch( dispID )
{
case DISPID_HTMLFORMELEMENTEVENTS2_ONSUBMIT:
::AfxMessageBox("提交表单");
break;
}
  return NOERROR;
  }
};
为什么程序执行没反应,根本就执行不到Invoke里面来(加断点)
执行到hr = pCP->Advise((IUnknown*)&vEvent,&pdwCookie);
这一句时,pdwCookie的值为0,意思是说连接无效?
由于我对COM可连接对象了解甚少,也不知道上面这些代码(用别人的)结构对不对,
大哥们给看看啊!!

解决方案 »

  1.   

    hr = pCP->Advise((IUnknown*)&vEvent,&pdwCookie);
    把CComVariant*强制转换成IUnknown*,这句编译能通过?
      

  2.   

    "CComQIPtr < IHTMLFormElement > spFormElement = pDisp;   
    pDisp->Release();  "
    不能释放把,应该是同一个地址,释放了,上面也没了
      

  3.   


    可以编译通过啊 ,如果不加(IUnknown*),编译的时候出错,说是cannot convert 参数1 from'ATL::CComVariant *__w64' to 'IUnknown'
      

  4.   


    应该不会吧,因为已经CComQIPtr < IHTMLFormElement > spFormElement = pDisp 了,以后用的就是spFormElement了
      

  5.   

    疑问:是不是因为 在MFC类库中,CCmdTarget类是 MFC 支持 COM 的基本类,CCmdTarget类实现了IUnknown接口,并通过嵌套类和接口映射表机制提供多接口支持 呢?
      

  6.   

    重新写了个接收器类:
    //DOMEventHandler.h#pragma once
    #include "oaidl.h"
    #include "ExDispID.h"
    class CDOMEventHandler :
    public IDispatch
    {
    public:
    CDOMEventHandler(void);
    public:
    ~CDOMEventHandler(void); HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject);
    DWORD __stdcall AddRef();
        DWORD __stdcall Release();

    STDMETHOD(GetTypeInfoCount)(unsigned int FAR* pctinfo) { return E_NOTIMPL; }   
        STDMETHOD(GetTypeInfo)(unsigned int iTInfo, LCID  lcid, ITypeInfo FAR* FAR*  ppTInfo) { return E_NOTIMPL; }   
        STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgDispId) { return S_OK; }   
    STDMETHOD(Invoke)(DISPID dispIdMember   
            , REFIID riid   
            , LCID lcid   
            , WORD wFlags   
            , DISPPARAMS* pDispParams   
            , VARIANT* pVarResult   
            , EXCEPINFO * pExcepInfo   
            , UINT * puArgErr   
            );   };
    //DOMEventHandler.cpp#include "StdAfx.h"
    #include "DOMEventHandler.h"
    #include "ExDispID.h"
    #include <mshtmdid.h>
    CDOMEventHandler::CDOMEventHandler(void)
    {
    }CDOMEventHandler::~CDOMEventHandler(void)
    {
    }HRESULT __stdcall CDOMEventHandler::QueryInterface(REFIID riid, void** ppvObject)   
    {   
        *ppvObject = NULL;   
        if (IsEqualGUID(riid, IID_IUnknown))   
            *ppvObject = reinterpret_cast<void**>(this);   
        if (IsEqualGUID(riid, IID_IDispatch))   
            *ppvObject = reinterpret_cast<void**>(this);   
        if (*ppvObject)   
        {   
            ((IUnknown*)*ppvObject)->AddRef();   
            return S_OK;   
        }   
        else  
        {   
            return E_NOINTERFACE;   
        }   
    }   
    DWORD __stdcall CDOMEventHandler::AddRef()   
    {   
        return 1;   
    }   
    DWORD __stdcall CDOMEventHandler::Release()   
    {   
        
            return 0;   
         
    }   
    HRESULT CDOMEventHandler::Invoke(DISPID dispIdMember,   
                                  REFIID riid,   
                                  LCID lcid,   
                                  WORD wFlags,   
                                  DISPPARAMS* pDispParams,   
                                  VARIANT* pVarResult,   
                                  EXCEPINFO * pExcepInfo,    
                                  UINT * puArgErr)   
    {   
    ::AfxMessageBox("进入Invoke");
        if (dispIdMember == DISPID_HTMLFORMELEMENTEVENTS2_ONSUBMIT)   
        {   
    ::AfxMessageBox("提交页面");
        }   
        return S_OK;   
    }  建立连接:
    IDispatch *pDisp = NULL; //取得第 i 项表单 
    hr = spElementCollection->item( CComVariant( i ), CComVariant(), &pDisp ); 

    if ( FAILED( hr ) ) continue;  CComQIPtr < IHTMLFormElement > spFormElement = pDisp; 
    pDisp->Release(); 
    CComPtr <CDOMEventHandler> pAboutWebEvent;
     CComVariant vEvent;
    vEvent.pdispVal = ( IDispatch* )pAboutWebEvent; 
    //vEvent.vt = VT_DISPATCH; IConnectionPointContainer* pCPC = NULL;
    IConnectionPoint* pCP = NULL;
    DWORD pdwCookie = NULL;
    hr=spFormElement->QueryInterface( IID_IConnectionPointContainer,(void**)&pCPC );
    if ( hr == S_OK )
    {
    hr = pCPC->FindConnectionPoint(DIID_HTMLFormElementEvents2,&pCP);
    if ( hr == S_OK )
    {
    HRESULT hr1;
    hr1 = pCP->Advise((IUnknown*)&vEvent,&pdwCookie);//(IUnknown*)
    //Invoke();
    }
    pCPC->Release();还是不行,Invoke没有被调用
      

  7.   

    调试的时候vEvent为{VT_EMPTY},pdwCookie的值始终为0,证明是连接无效啊,求高手解答啊!!!
      

  8.   

    你的 CComPtr <CDOMEventHandler> pAboutWebEvent; 不是全局变量?
      

  9.   


    是全局的,在.cpp开头就声明了,我只是想把下面的几句联系到一块儿,就那样写了,我的错!!!
      

  10.   

    vEvent不要了,
    hr = pCP->Advise((IUnknown*)&vEvent,&pdwCookie);
    这句改为CComQIPtr<IUnknown, &IID_IUnknown> spUnk = pAboutWebEvent;
    hr = pCP->Advise(spUnk ,&pdwCookie);
      

  11.   


    也不行啊,还是一样的情况,不知道我那个类写的有没有问题(参照)pdwCookie的值始终为0, spUnk调试之后的值为{0X00000000} 
      

  12.   

    CComQIPtr<IUnknown, &amp;IID_IUnknown> spUnk = pAboutWebEvent;如果执行过这句之后 pAboutWebEvent 非空 而 spUnk 为空,说明你写的类的QueryInterface有问题
      

  13.   

    CComPtr <CDOMEventHandler> pAboutWebEvent;
    你这里没有创建CDOMEventHandler的对象!! 当然spUnk是空指针了~
      

  14.   


    CComQIPtr<IUnknown, &amp;IID_IUnknown> spUnk = pAboutWebEvent;
    执行完这句之后,pAboutWebEvent的值也是{0X00000000}
      

  15.   


    咋看不明白呢,这一句不是在.cpp开头儿已经创建为全局的了嘛
      

  16.   

    你这样只是定义了一个智能指针,但它指向的接口为空!“执行完这句之后,pAboutWebEvent的值也是{0X00000000}”准确的说应该是一直为{0X00000000}
      

  17.   

    是不是要在类的头文件中得BEGIN_COM_MAP这个地方做点儿文章呢?
      

  18.   

    你现在pAboutWebEvent是空指针,没有指向任何对象。又需要一个对象,你说该咋个整喃?
      

  19.   

    那不容易呀,CDOMEventHandler pAboutWebEvent; 关键是与CComPtr <CDOMEventHandler> pAboutWebEvent如何衔接起来出了问题
      

  20.   

    哈哈 今天早上才去图书馆借了HTML的书 还没有学习呢
      

  21.   

    你说的对,声明对像了,要指针就没有用了,连接部分做如下修改:
    CDOMEventHandler pAboutWebEvent;(全局)
    CComQIPtr<IUnknown, &IID_IUnknown> spUnk = pAboutWebEvent;这一句不能要了,还得改回原来的
    CComVariant vEvent;
    vEvent.pdispVal = ( IDispatch* )&pAboutWebEvent;  //CComQIPtr<IUnknown, &IID_IUnknown> spUnk = pAboutWebEvent;
    IConnectionPointContainer* pCPC = NULL;
    IConnectionPoint* pCP = NULL;
    DWORD pdwCookie = NULL;
    hr=spFormElement->QueryInterface( IID_IConnectionPointContainer,(void**)&pCPC );
    if ( hr == S_OK )
    {
    hr = pCPC->FindConnectionPoint(DIID_HTMLFormElementEvents2,&pCP);
    if ( hr == S_OK )
    {
    HRESULT hr1;
    hr1 = pCP->Advise((IUnknown*)&vEvent,&pdwCookie);
    //hr1 = pCP->Advise(spUnk,&pdwCookie);
    if ( FAILED( hr1 ) )    ::AfxMessageBox("bbb");

    }
    pCPC->Release();这在以前已经测试过,结果自然还是不会调用Invoke,这种情况下,pAboutWebEvent不为{0X00000000},而是{m_dwRef=1},其中m_dwRef是在类中的一个计数器吧,但是,vEvent的值为{VT_EMPTY}, pdwCookie的值还依然为0———无效的连接
      

  22.   

    重新看一下那个类吧:#include "StdAfx.h"
    #include "DOMEventHandler.h"
    #include "ExDispID.h"
    #include <mshtmdid.h>
    CDOMEventHandler::CDOMEventHandler(void):m_dwRef(1)
    {
    }CDOMEventHandler::~CDOMEventHandler(void)
    {
    } DWORD m_dwRef;HRESULT __stdcall CDOMEventHandler::QueryInterface(const struct _GUID &riid,void ** ppv){
            *ppv = NULL;        if (IID_IUnknown == riid)
            {
                *ppv = (LPUNKNOWN)this;
                AddRef();
                return NOERROR;
            }
            else if (IID_IDispatch == riid)
            {
                *ppv = (IDispatch*)this;
                AddRef();
                return NOERROR;
            }
            else
            {
                return E_NOTIMPL;
            }
        }
    DWORD __stdcall CDOMEventHandler::AddRef()   
    {   
        //return 1;   
    return ++m_dwRef;
    }   
    DWORD __stdcall CDOMEventHandler::Release()   
    {   
        //return 0;   
        if (--m_dwRef == 0) 
        { 
    delete this; 
    return 0; 
        }
         return m_dwRef;
    }   
    HRESULT CDOMEventHandler::Invoke(DISPID dispIdMember,   
                                  REFIID riid,   
                                  LCID lcid,   
                                  WORD wFlags,   
                                  DISPPARAMS* pDispParams,   
                                  VARIANT* pVarResult,   
                                  EXCEPINFO * pExcepInfo,    
                                  UINT * puArgErr)   
    {   
    ::AfxMessageBox("进入Invoke");
        if (dispIdMember == DISPID_HTMLFORMELEMENTEVENTS2_ONSUBMIT)   
        {   
    ::AfxMessageBox("提交页面");
        }   
        return S_OK;   
    }   
      

  23.   

    连接部分做如下修改,pdwCookie的值就不为0了CDOMEventHandler pAboutWebEvent;//(全局)
    //把下面两句
    //CComVariant vEvent;
    //vEvent.pdispVal = ( IDispatch* )pAboutWebEvent;
    //改为:
    CComQIPtr<IUnknown, &IID_IUnknown> spUnk = &pAboutWebEvent;
    IConnectionPointContainer* pCPC = NULL;
    IConnectionPoint* pCP = NULL;
    DWORD pdwCookie = NULL;
    hr=spFormElement->QueryInterface( IID_IConnectionPointContainer,(void**)&pCPC );
    if ( hr == S_OK )
    {
    hr = pCPC->FindConnectionPoint(DIID_HTMLFormElementEvents2,&pCP);
    if ( hr == S_OK )
    {
         
         //把下面一句       //hr= pCP->Advise((IUnknown*)&vEvent,&pdwCookie);
                 //改为
                   hr= pCP->Advise(spUnk,&pdwCookie);
         if ( FAILED( hr1 ) )    
                        ::AfxMessageBox("Advise调用失败");
    }
    pCPC->Release();

    }
    在上述代码中,我估计是hr= pCP->Advise((IUnknown*)&vEvent,&pdwCookie);这一句出了问题,jameshooo大哥说的很有道理,不应该把CComVariant*强制转换成IUnknown*,
    经过修正后也根本不需要CComVariant但是,类CDOMEventHandler中的Invoke 依然没有被调用,连接部分执行完毕后直接就推出程序了,切盼大哥们指教
      

  24.   

    CComQIPtr<IUnknown, &IID_IUnknown> spUnk = pAboutWebEvent;这一句不能要了,还得改回原来的
    -----------
    这句为啥不能要了呢?
    改成这样:
    CDOMEventHandler pAboutWebEvent;(全局)
    CComQIPtr<IUnknown, &IID_IUnknown> spUnk = &pAboutWebEvent;
    hr= pCP->Advise(spUnk,&pdwCookie);
    就可以!
      

  25.   

    晕,没有看到你的36楼!连接部分执行完毕后直接就推出程序了
    -------------
    你连接成功后,需要去触发submit事件
      

  26.   


    skyxie大哥能帮我实现不?这个我可确实不会另外,我的工程原意是当用户用鼠标点击网页中的“提交”按钮,系统响应DISPID_HTMLFORMELEMENTEVENTS2_ONSUBMIT事件,当程序获取此网页的DISPID_HTMLFORMELEMENTEVENTS2_ONSUBMIT事件后,再进行其他的操作,我是这样想的,不知与skyxie大哥的意思“连接成功后,需要去触发submit事件”是否一致,望skyxie大哥明示啊!!!
      

  27.   

    本帖最后由 skyxie 于 2010-09-10 18:12:37 编辑
      

  28.   

    Jameshoo很认真负责,你问他吧, 我是伪专家, 也真的非常忙, 实在抱歉了 ..