Отловить событие OLE-объекта
От: Аноним  
Дата: 22.03.04 12:10
Оценка:
Имеется некий OLE-объект.
MyObject = CreateOleObject("XXX.XXX");

Этот объект имееет событие OnDataChange(...).

Может, для кого-нибудь это покажется элементарным, но как отловить это событие в своей программе?
И одна большая просьба, пусть пример кода будет на Builder'е. На VB для Excel я это уже видел, а на Си подобное не получится.
Re: Отловить событие OLE-объекта
От: Alex  
Дата: 22.03.04 23:21
Оценка:
Так же легко как в VB не получится. Нужно реализовать твой диспинтерфейс, примерно так (на работоспособность не проверял):



//хидер
#include <atl/atlbase.h>

class PACKAGE TMyEvents : public IMyEvents
{
private:
    LPUNKNOWN* server;
    DWORD Cookie;
public:
    __fastcall TMyEvents(), server(0){};
    __fastcall ~TMyEvents();
  // IUnknown
    HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject);
    ULONG   STDMETHODCALLTYPE AddRef();
    ULONG   STDMETHODCALLTYPE Release();
  // IDispatch
    HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* pctInfo);
    HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT, LCID, ITypeInfo** ppTypeInfo);
    HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID, LPOLESTR*, UINT, LCID, DISPID*);
    HRESULT STDMETHODCALLTYPE Invoke(DISPID dispid, REFIID iid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
                                     VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgError);
    void __fastcall Connect(LPUNKNOWN _server);
    void __fastcall Disconnect();
};


//зеализация
__fastcall TMyEvents::~TMyEvents()
{
  Disconnect();
}

HRESULT STDMETHODCALLTYPE TMyEvents::QueryInterface(REFIID iid, void **ppvObject)
{
  *ppvObject = 0;
  if (iid == IID_IUnknown || iid == IID_IDispatch || iid == DIID_MyEvents){
    *ppvObject = this;
  }else
    return E_NOINTERFACE;
  return S_OK;
}

ULONG STDMETHODCALLTYPE TMyEvents::AddRef()
{
  return 2;//при желании можно сделать счётчик, но в принципе он сдесь не нужен
}

ULONG STDMETHODCALLTYPE TMyEvents::Release()
{
  return 1;//при желании можно сделать счётчик, но в принципе он сдесь не нужен
}

HRESULT STDMETHODCALLTYPE TMyEvents::GetTypeInfoCount(UINT* pctInfo)
{
  *pctInfo = 0;
  return S_OK;
}

HRESULT STDMETHODCALLTYPE TMyEvents::GetTypeInfo(UINT, LCID, ITypeInfo** ppTypeInfo)
{
  *ppTypeInfo = 0;
  return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE TMyEvents::GetIDsOfNames(REFIID, LPOLESTR*, UINT, LCID, DISPID*)
{
  return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE TMyEvents::Invoke(DISPID dispid, REFIID iid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
                                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgError)
{
  switch(dispid)
  {
    case 1://надо знать идентификатор твоего события
      ShowMessage("твоё событие пришло");
      break;
  }
  return S_OK;
}

void __fastcall TMyEvents::Connect(_server)
{
  if (server)
    Disconnect();
  server=_server;
  if (!server)
    return;
  server->AddRef();
  CComPtr<IConnectionPointContainer> icpc;
  if (SUCCEEDED(server->QueryInterface(IID_IConnectionPointContainer, (void**)&icpc)))
  {
    CComPtr<IConnectionPoint> icp;
    if (SUCCEEDED(icpc->FindConnectionPoint(Events_ID, &icp)))
      icp->Advise(this, &Cookie);
  }
}

void __fastcall TMyEvents::Disconnect()
{
  if (!server)
    return;
  CComPtr<IConnectionPointContainer> icpc;
  if (SUCCEEDED(server->QueryInterface(IID_IConnectionPointContainer, (void**)&icpc)))
  {
    CComPtr<IConnectionPoint> icp;
    if (SUCCEEDED(icpc->FindConnectionPoint(Events_ID, &icp)))
      icp->Unadvise(Cookie);
  }
  server->Release();
  server=0;
}

//используем так
TMyEvents MyEvents;
MyEvents.Connect(MyObject);//после этого события ловятся
Re[2]: Отловить событие OLE-объекта
От: L0N6 Россия  
Дата: 23.03.04 09:04
Оценка:
Во-первых, компильнуть этот пример у меня не получилось — несколько ошибок (не настолько уж я силен в Builder'е).
А во-вторых, событие с параметрами. Как их достать? Через
DISPPARAMS *pDispParams
?

Может, все-таки, есть пример по-проще?
Re[3]: Отловить событие OLE-объекта
От: Alex  
Дата: 23.03.04 12:20
Оценка:
Здравствуйте, L0N6, Вы писали:

LN>Во-первых, компильнуть этот пример у меня не получилось — несколько ошибок (не настолько уж я силен в Builder'е).

LN>А во-вторых, событие с параметрами. Как их достать? Через
DISPPARAMS *pDispParams
?


LN>Может, все-таки, есть пример по-проще?


Чтобы сделать попроще надо использовать оболочки (например, TEventDispatcher), а этот пример демонстрирует как это делается.
Работоспособный пример (архив) здесь.
Re[4]: Отловить событие OLE-объекта
От: L0N6 Россия  
Дата: 24.03.04 05:22
Оценка:
Здравствуйте, Alex, Вы писали:

A>Чтобы сделать попроще надо использовать оболочки (например, TEventDispatcher), а этот пример демонстрирует как это делается.

A>Работоспособный пример (архив) здесь.

Огромное спасибо за пример, все заработало.

З.Ы. У меня получилось, что параметры, передаваемые вместе с событием, идут в обратном порядке. Это правильно?
Re[5]: Отловить событие OLE-объекта
От: ned Австралия  
Дата: 24.03.04 14:27
Оценка:
Здравствуйте, L0N6, Вы писали:

LN>З.Ы. У меня получилось, что параметры, передаваемые вместе с событием, идут в обратном порядке. Это правильно?


Правильно.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.