关于在IE中响应ActiveX事件的问题,谁能找到社区对应贴子,或者给出一些参考代码。

 所属目录:Java   |   类型:技术问答   |   时间:2007-05-21
 问题:

http://community.csdn.net/expert/faq/faq_index.asp?id=187805  
   
   
   
   
  q   :   关于在ie中响应activex事件的问题。100分    
  主要解答者:   lop5712   提交人:   freeshoot    
  感谢:      
  审核者:   wangweixing2000   社区对应贴子:   查看    
            a   :      
   
  在mfc     activex     wizzard基础上class     wizzard     添加了若干method和event。      
            如果通过html中的vbscript调用activex控件的method,然后在method中      
  firexxevent,一切都正常。通过vbscript能正确响应该事件。      
            然而,当用控件内部自己创建的工作线程firexxevent时,ie却不能正确      
  响应该事件,在调试状态,还能看见异常发生,控件内的invoke      
  方法没返回正确值。(在tstcon32中调试时,能看见事件发生)      
     
  ---------------------------------------------------------------      
     
  那是因为fireevent实际上是调用客户端实现的一个接口(在这就是ie实现的idispatch接口)的方法,而activex控件一定是放在sta套间(虽然也可以,但应该没人实现为放在mta)的,因此工作线程调用ie的idispatch接口一定且必须是代理接口,这个接口必须通过汇集得到(以创建代理对象)。      
     
  即需要在主线程调用comarshalinterface来列集ie的那个idispatch接口,再在工作线程调用counmarshalinterface来散集idispatch接口,进而在工作线程中通过散集的idispatch接口发起事件。由于楼主是在线程间汇集接口,所以可以使用comarshalinterthreadinterfaceinstream和cogetinterfaceandreleasestream代替上面的两个函数进行汇集,效率会有所提高。      
     
  而这样做(即建立代理对象)的实际工作工程,与楼主说的“另外”是异曲同工的,所以楼主要是闲上面麻烦,可以按照楼主说的“另外”来实现。      
     
  还有就是colecontrol是mfc的包装类,其中使用了一些mfc的底层的机制(如线程状态等),所以当欲跨线程传递activex对象的指针时,不可直接传递colecontrol*之类,否则就有可能发生断言失败,而应该通过fromhandle和detach来传递句柄(不过这样就不能使用派生类的相关成员函数)。因此楼主如果想使用上面的方法,需先获得客户的接口指针(即idispatch),然后将其列集得到的istream*作为线程参数传递给工作线程,而不要使用直接的this。      
     
 

· 网友精彩回答:

发表者:krh2001

给你一个我写的atl   线程类,   已经包装了   接口指针列集,可以直接在run   中使用   传入的接口来触发事件:  
   
   
  //   comthread.h:   interface   for   the   ccomthread   class.  
  //  
  //////////////////////////////////////////////////////////////////////  
   
  #if   !defined(afx_comthread_h__050cc613_79d4_4257_93cf_4e67f98b2b82__included_)  
  #define   afx_comthread_h__050cc613_79d4_4257_93cf_4e67f98b2b82__included_  
   
  #if   _msc_ver   >   1000  
  #pragma   once  
  #endif   //   _msc_ver   >   1000  
   
  #include   <windows.h>  
   
  template<class   devied,   class   interface,   const   iid*   piid   =   &__uuidof(interface)>  
  class   ccomthread      
  {  
  protected:  
  ccomthread()  
  {  
  m_hthread   =   null;  
  m_dwthreadid   =   0;  
  m_pstream   =   null;  
  }  
  virtual   ~ccomthread()  
  {  
  close();  
  }  
   
  public:  
  bool   start()  
  {  
  if(m_hthread   !=   null)  
  return   false;  
   
  devied*   pdevied   =   ((devied*)this);  
  m_pstream   =   null;  
  hresult   hr   =   0;  
  hr   =   comarshalinterthreadinterfaceinstream(*piid,    
  static_cast<interface*>(pdevied),   &m_pstream);  
   
  //   create   thread   and   pass   the   thend   process   the   this   ptr  
  m_hthread   =   createthread(null,   0,   threadfnc,   (lpvoid)   this,   0,   &m_dwthreadid);  
  return   s_ok;  
  }  
   
  bool     wait(dword   dwtime   =   infinite)  
  {  
  return   atlwaitwithmessageloop(m_hthread);  
  }  
  void     terminate(dword   dwexitcode)  
  {  
  if(m_hthread   !=   null)  
  terminatethread(m_hthread,   dwexitcode);  
  }  
  void     close()    
  {  
  if(m_hthread   !=   null)    
  {  
  closehandle(m_hthread);  
  m_hthread   =   null;  
  }  
  }  
   
  private:  
  handle     m_hthread;  
  dword       m_dwthreadid;  
  lpstream     m_pstream;  
   
  static   dword   winapi   threadfnc(lpvoid   lp)  
  {  
  ccomthread<devied,   interface,   piid>*   pthis   =    
  (ccomthread<devied,   interface,   piid>*)lp;  
  return   pthis->_run();  
  }  
   
  dword   _run()  
  {  
  ccominit   cominit;  
  hresult     hr;  
  ccomqiptr<interface,   piid>   spitf;  
   
  if(m_pstream)  
  hr   =   cogetinterfaceandreleasestream(m_pstream,   *piid,   (lpvoid*)&spitf);  
   
  dword   dw   =   static_cast<devied*>(this)->run(spitf);  
   
  spitf.release();  
   
  return   dw;  
  }  
  };  
   
   
   
  #endif   //   !defined(afx_comthread_h__050cc613_79d4_4257_93cf_4e67f98b2b82__included_)  
   
   
   
   
  使用很简单,象其它模板一样添加到继承列表:  
  class   atl_no_vtable   cremote   :    
  public   ccomobjectrootex<ccomsinglethreadmodel>,  
  public   ccomcoclass<cremote,   &clsid_remote>,  
  public   iconnectionpointcontainerimpl<cremote>,  
  public   idispatchimpl<iremote,   &iid_iremote,  
  &libid_remotelinklib,   rllibvermaj,   rllibvermin>,  
  public   iremoteeventsfire,  
  public   ccomthread<cremote,   iremoteeventsfire,   &iid_iremoteeventsfire>,  
  public   cproxy_iremoteevents<   cremote   >  
  {  
  public:  
   
        .....  
   
        dword   run(iremoteeventsfire*   pfireitf)     //   这个是线程函数,必需实现,   否则编译不了  
        {  
                    ....  
                    pfireitf->firethreadstart();       //   事件  
   
                    ...  
   
                   
                    return   0;  
        }  
   
   
  };  
   
   
 

.
处理 SSI 文件时出错
© 2006-2008 All Rights Reserved