client端: 
class CEvent: public IUnknown 

public: 
    CEvent() 
    {}; 
    HRESULT __stdcall QueryInterface(REFIID iid, void** ppv); 
    long  onspeak(BSTR leirong);//回叫函数 
    ULONG __stdcall AddRef(); 
    ULONG __stdcall Release(); 
    long m_cRef; };//接收器 GUID emapCLSID; 
HRESULT hresult= CoInitialize( NULL ); 
Im *pUnknown; 
hresult = ::CLSIDFromProgID(L"Project1.mycomclass",&emapCLSID); 
hresult = CoCreateInstance(emapCLSID,NULL,CLSCTX_ALL,IID_Im,(void**)&pUnknown); 
//注册回调 
CEvent * pEvent= new CEvent(); 
pEvent->AddRef(); 
IConnectionPointContainer* pConnectionPointContainer = NULL; 
IConnectionPoint* pConnectionPoint = NULL ; 
DWORD dwCookie; 
hresult = pUnknown->QueryInterface(IID_IConnectionPointContainer, (void**)  &pConnectionPointContainer);        hresult = pConnectionPointContainer->FindConnectionPoint(DIID_ImycomclassEvents, &pConnectionPoint); 
if(SUCCEEDED(hresult)) 
hresult=pConnectionPoint->Advise((IUnknown*)pEvent, &dwCookie);//这这一步时候,返回错误值,hresult=  -2147220990,错误是“不能打开当前线程的存取令牌  ” 
pConnectionPoint->Release(); 服务器端视这样的: 
class ATL_NO_VTABLE TmycomclassImpl : 
  public CComObjectRootEx <CComSingleThreadModel>, 
  public CComCoClass <TmycomclassImpl, &CLSID_mycomclass>, 
  public IConnectionPointContainerImpl <TmycomclassImpl>, 
  public TEvents_mycomclass <TmycomclassImpl>, 
  public Im 

public: 
  TmycomclassImpl() 
  { 
  }   // Data used when registering Object 
  // 
  DECLARE_THREADING_MODEL(otApartment); 
  DECLARE_PROGID("Project1.mycomclass"); 
  DECLARE_DESCRIPTION("");   // Function invoked to (un)register object 
  // 
  static HRESULT WINAPI UpdateRegistry(BOOL bRegister) 
  { 
    TTypedComServerRegistrarT <TmycomclassImpl> 
    regObj(GetObjectCLSID(), GetProgID(), GetDescription()); 
    return regObj.UpdateRegistry(bRegister); 
  } 
BEGIN_COM_MAP(TmycomclassImpl) 
  COM_INTERFACE_ENTRY(Im) 
  COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer) 
END_COM_MAP() BEGIN_CONNECTION_POINT_MAP(TmycomclassImpl) 
  CONNECTION_POINT_ENTRY(DIID_ImycomclassEvents) 
END_CONNECTION_POINT_MAP() // Im 
public:   int STDMETHODCALLTYPE mytest(int test); 
}; 
extern "C" const __declspec(selectany) GUID LIBID_Project1 = {0x74EB1205, 0x8D05, 0x43EE,{ 0x8A, 0x88, 0x6F,0x01, 0x70, 0xE8,0x93, 0x78} }; 
extern "C" const __declspec(selectany) GUID IID_Im = {0xE8C6F90B, 0x2008, 0x4F0F,{ 0x82, 0x45, 0x5E,0xA2, 0x12, 0x99,0x2F, 0x73} }; 
extern "C" const __declspec(selectany) GUID DIID_ImycomclassEvents = {0x0D1685B3, 0x4B28, 0x4C03,{ 0xA5, 0xB3, 0x90,0xE5, 0xE2, 0x8A,0x47, 0x1B} }; 
extern "C" const __declspec(selectany) GUID CLSID_mycomclass = {0xE9F55514, 0xDB1B, 0x4DF9,{ 0xB0, 0xCB, 0xC0,0x57, 0xEA, 0xEE,0xB6, 0xE1} }; idl: 

  uuid(74EB1205-8D05-43EE-8A88-6F0170E89378), 
  version(1.0), 
  helpstring("Project1 Library") ] 
library Project1 
{   importlib("stdole2.tlb");   [ 
    uuid(E8C6F90B-2008-4F0F-8245-5EA212992F73), 
    version(1.0), 
    helpstring("Interface for mycomclass Object"), 
    oleautomation 
  ] 
  interface Im: IUnknown 
  { 
    [ 
    id(0x00000001) 
    ] 
    int _stdcall mytest([in] int test ); 
  };   [ 
    uuid(0D1685B3-4B28-4C03-A5B3-90E5E28A471B), 
    version(1.0), 
    helpstring("Events interface for mycomclass Object") 
  ] 
  dispinterface ImycomclassEvents 
  { 
    properties: 
    methods: 
    [ 
    id(0x00000001) 
    ] 
    HRESULT onspeak([in] BSTR leirong ); 
  };   [ 
    uuid(E9F55514-DB1B-4DF9-B0CB-C057EAEEB6E1), 
    version(1.0), 
    helpstring("mycomclass") 
  ] 
  coclass mycomclass 
  { 
    [default] interface Im; 
    [default, source] dispinterface ImycomclassEvents; 
  }; }; //这是服务端的回叫类.bcb自己生成的. 
template <class T> 
class TEvents_mycomclass : public IConnectionPointImpl <T, 
                                                &DIID_ImycomclassEvents, 
                                                CComUnkArray <CONNECTIONPOINT_ARRAY_SIZE> > 
/* Note: if encountering problems with events, please change CComUnkArray to CComDynamicUnkArray in the line above. */ 

public: 
  HRESULT        Fire_onspeak(BSTR leirong); 
protected: 
  ImycomclassEventsDisp m_EventIntfObj; 
}; template <class T> HRESULT 
TEvents_mycomclass <T>::Fire_onspeak(BSTR leirong) 

  T * pT = (T*)this; 
  pT->Lock(); 
  IUnknown ** pp = m_vec.begin(); 
  while (pp < m_vec.end()) 
  { 
    if (*pp != NULL) 
    { 
      m_EventIntfObj.Attach(*pp); 
      m_EventIntfObj.onspeak(leirong); 
      m_EventIntfObj.Attach(0); 
    } 
    pp++; 
  } 
  pT->Unlock(); 

想用连接点,实现服务器回叫客户端事件,不知道是出什么错误了,高手指教啊!

解决方案 »

  1.   

    客户端Advise加入连接点的代码地方看是否正确,检查返回错误信息
      

  2.   


    我想是我的接收器谢的有问题!
    if(SUCCEEDED(hresult)) 
    hresult=pConnectionPoint->Advise((IUnknown*)pEvent, &dwCookie);//这这一步时候,返回错误值,hresult=  -2147220990,错误是“不能打开当前线程的存取令牌  ”接收器有什么特殊要求吗?
      

  3.   

    class CEvent: public IUnknown ///////////////////
    class CEvent: public IDispatch
      

  4.   

    是我的接收器出问题了,
    现在是pConnectionPoint->Advise((IUnknown*)pEvent, &dwCookie);//没问题了
    但是:
    class CEvent: public ImycomclassEvents//ImycomclassEvents是服务器的event接口,他继承了 IDispatch的函数
    virtual /* [local] */ HRESULT STDMETHODCALLTYPE Invoke( 
                /* [in] */ DISPID dispIdMember,
                /* [in] */ REFIID riid,
                /* [in] */ LCID lcid,
                /* [in] */ WORD wFlags,
                /* [out][in] */ DISPPARAMS *pDispParams,
                /* [out] */ VARIANT *pVarResult,
                /* [out] */ EXCEPINFO *pExcepInfo,
                /* [out] */ UINT *puArgErr) = 0;
    是纯虚函数 CEvent要实现它,要不服务器会报错
    我联调了是这个函数导致服务器报错的,这个函数怎么实现呢?
      

  5.   

    怎么实现?直接返回 returnS_OK;?
      

  6.   

    要么继承 IDispatchImpl 它帮你实现
      

  7.   

    不继承 IDispatchImpl ,这样要写太多的东西,想服务器一样,怎么实现invoke呢?
      

  8.   

    接收器的QueryInterface如何实现的?估计是这儿的问题。  关于这个问题你可以看《COM原理与应用》的相关章节,代码都有很详细。
      

  9.   

    STDMETHOD(QueryInterface)(const struct _GUID &iid,void ** ppv);
    ULONG __stdcall CSink::AddRef(void);
    ULONG __stdcall CSink::Release(void);
    STDMETHOD raw_Fire_onspeak(BSTR leirong);//
    STDMETHODIMP CEvent::raw_Fire_onspeak(BSTR leirong)
    {
    }