2010-11-04 4 views
1

Я написал простой COM-сервер DLL inproc с одним простым COM-объектом. COM-объект реализует точку подключения.Предоставление реализации IDispatch для клиента точки подключения

Я знаю, как создать клиент ATL, который происходит от IDispEventImpl, и использует карту раковины для упрощения этого процесса.

Но для демонстрации я хотел бы создать консольное приложение win32, которое использует класс, который вызывает мой простой COM-объект, а затем действует как приемник точки подключения.

Я не знаю, как обеспечить реализацию IDispatch - может кто-то рекомендовать документацию по этому поводу, поскольку я не могу найти (у меня есть ATL Internals, но это, похоже, не охватывает то, что я необходимость).

Вот класс, я уже получил:

#pragma once 
#include <iostream> 
using namespace std; 

// Because we're implementing a connection points sink (_IPogFarmEvents) 
// in a non-ATL class, we must provide implementations for IUnknown and IDispatch. 

class KidWithAPogFarm : public _IPogFarmEvents 
{ 
    private: 
     DWORD m_dwRefCount; 
     LONG m_lNumPogs; 

    public: 
     KidWithAPogFarm() : 
     m_dwRefCount (0), 
     m_lNumPogs (0) 
     { 
     } 

     ~KidWithAPogFarm() 
     { 
     } 


     // -- IUnknown 
     HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) 
     { 
      if (iid == DIID__IPogFarmEvents) 
      { 
       m_dwRefCount++; 
       *ppvObject = (void *)this; 
       return S_OK; 
      } 
      if (iid == IID_IUnknown) 
      { 
       m_dwRefCount++; 
       *ppvObject = (void *)this; 
       return S_OK; 
      } 
      return E_NOINTERFACE; 
     } 

     ULONG STDMETHODCALLTYPE AddRef() 
     { 
      m_dwRefCount++; 
      return m_dwRefCount; 
     } 

     ULONG STDMETHODCALLTYPE Release() 
     { 
      ULONG l; 
      l = m_dwRefCount--; 

      if (0 == m_dwRefCount) 
       delete this; 

      return l; 
     } 


     // -- IDispatch 
     STDMETHODIMP GetTypeInfoCount(UINT *pctinfo) 
     {  
      return E_NOTIMPL; 
     } 

     STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) 
     { 
      return E_NOTIMPL; 
     } 

     STDMETHODIMP GetIDsOfNames(const IID &riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) 
     { 
      return E_NOTIMPL; 
     } 
     STDMETHODIMP Invoke(DISPID dispIdMember, const IID &riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) 
     { 
      return E_NOT_IMPL; 
     } 

     // -- IAntFarmEvents 
     STDMETHODIMP OnFarmCreated(LONG lInitialPopulation) 
     { 
      m_lNumPogs = lInitialPopulation; 

      cout << "The kid has a pog farm with " << m_lNumPogs << " pogs " << endl; 
      return S_OK; 
     } 
}; 
+0

Внедрение IDispatch - это огромная боль; Я буду следовать советам Sharptooth и наследовать от IUnknown. – Luke

+0

Вы не должны использовать 'this' для' void * '- использовать' static_cast' для перевода в соответствующий интерфейс - см. Http://stackoverflow.com/questions/1742848/why-exactly-do-i-need-an -explicit-upcast-when-implementation-queryinterface-in-an для объяснения причин. – sharptooth

ответ

2

Поскольку у вас уже есть ATL вы можете проверить свои источники и посмотреть, как IDispatchImpl делает все эти вещи. IDispatch реализованы методы чтения данных из библиотеки типов в том же модуле, поскольку это самый простой и надежный способ, когда библиотека типов уже присутствует.

Также стоит отметить, что это довольно сложная тема для демонстрации на нем - вам нужно написать много кода, который на самом деле не дает никакого понимания. ИМО вам будет намного лучше, если вы реализуете интерфейс событий, который не наследуется от IDispatch, а скорее наследует напрямую от IUnknown - это покажет, как работают события, не затягивая слишком много внимания на внутреннюю работу IDispatch.

+0

У меня все получилось, но у меня были проблемы с CProxy_IPogFarmEvents :: Fire_OnFarmCreated.В частности, вызов pConnection-> Invoke() завершился с ошибкой, и я не мог понять, почему - и компилятор не сообщил мне много информации: S – 2010-11-04 14:30:34

+0

@free - что бы вы ни пришли с заменой, не будет работать так же , –

1

Я думаю, что самый простой способ сделать это через CreateStdDispatch

+0

Я посмотрю на это, я никогда не сталкивался с этим раньше, спасибо. – 2010-11-04 14:38:06

1

Вы можете использовать this реализацию IDispatch.

0

Это не совсем то, что вы ищете, но FireBreath использует IDispatchEx и точки подключения для обеспечения элемента управления ActiveX, который работает в IE. Поскольку FireBreath является абстракцией, позволяющей писать плагины один раз и использоваться во всех основных браузерах, интерфейс IDispatch должен быть написан вручную - включая точки подключения.

Код может быть немного запутанным, так как существует шаблонный класс mixin, используемый для предоставления IDispatch и ConnectionPoints для двух разных классов объектов COM, но это может помочь.

Вы уже приняли ответ, но, возможно, он все равно будет помогать. Извините, я не видел вопроса раньше.

Смежные вопросы