Udostępnij za pośrednictwem


Obsługa zdarzeń w modelu COM

W obsłudze zdarzeń modelu COM, ustawić zdarzenia źródło i zdarzenie odbiornika za pomocą źródło_zdarzenia i event_receiver atrybuty, odpowiednio, określając type=com.Te atrybuty wstrzyknąć odpowiedni kod niestandardowy, wysyłki i podwójny interfejsach, klasy, do których są stosowane do obsługi zdarzeń za pośrednictwem punktów połączenia COM i ognia zdarzenia.

Deklarowanie zdarzeń

W klasie źródła zdarzeń, użyj klasy __event słowa kluczowego w deklaracji interfejsu do deklarowania metod tego interfejsu jako zdarzenia.Zdarzenia interfejsu są wywoływane podczas wywołania metody interfejsu.Metody interfejsów zdarzeń może mieć zero lub więcej parametrów (które powinny być w parametry).Zwracany typ może być typu void lub każdym integralną.

Definiowanie obsługi zdarzeń

Odbiornik klasy event służy do definiowania procedury obsługi zdarzeń, które są metody z podpisami (zwracanymi typami wywoływania konwencje i argumenty), pasujące zdarzenie, które będą je obsługiwać.Dla zdarzeń COM konwencji wywoływania musi odpowiadać; zobacz Układ zależnych zdarzeń COM poniżej szczegółowe informacje.

Spinanie obsługi zdarzeń do zdarzeń

Również w klasie zdarzeń odbiornika, używana jest funkcja wewnętrzna __hook do kojarzenia zdarzenia z obsługą zdarzeń i __unhook do dissociate zdarzeń z programów obsługi zdarzeń.Można hook kilka zdarzeń do programu obsługi zdarzeń lub kilka programów obsługi zdarzeń na zdarzenie.

[!UWAGA]

Zwykle istnieją dwie techniki umożliwiające odbiorcy zdarzeń COM definicji interfejsu źródła zdarzeń dostępu do.Pierwszy, jak pokazano poniżej, jest udostępnienie wspólnego pliku nagłówka.Druga jest użycie #import z embedded_idl przywóz kwalifikatora, tak, aby biblioteka typów źródła zdarzeń jest zapisywane w pliku .tlh kod generowany atrybut zachowane.

Wyzwalania zdarzenia

Ogień zdarzenie, po prostu wywołać metody w interfejsie zadeklarowana z __event słów kluczowych w przypadku źródła klasy.Jeśli obsługi mają zostały przechwycone w taki sposób, aby zdarzenia, zostanie wywołana programów obsługi.

hdcxwbd5.collapse_all(pl-pl,VS.110).gifKod zdarzenia COM

Poniższy przykład pokazuje, jak na ogień zdarzenia klasy COM.Aby skompilować i uruchomić przykład, zapoznaj się z komentarzy w kodzie.

// evh_server.h
#pragma once

[ dual, uuid("00000000-0000-0000-0000-000000000001") ]
__interface IEvents {
   [id(1)] HRESULT MyEvent([in] int value);
};

[ dual, uuid("00000000-0000-0000-0000-000000000002") ]
__interface IEventSource {
   [id(1)] HRESULT FireEvent();
};

class DECLSPEC_UUID("530DF3AD-6936-3214-A83B-27B63C7997C4") CSource;

I następnie serwera:

// evh_server.cpp
// compile with: /LD
// post-build command: Regsvr32.exe /s evh_server.dll
#define _ATL_ATTRIBUTES 1
#include <atlbase.h>
#include <atlcom.h>
#include "evh_server.h"

[ module(dll, name="EventSource", uuid="6E46B59E-89C3-4c15-A6D8-B8A1CEC98830") ];

[coclass, event_source(com), uuid("530DF3AD-6936-3214-A83B-27B63C7997C4")]
class CSource : public IEventSource {
public:
   __event __interface IEvents; 

   HRESULT FireEvent() {
      __raise MyEvent(123);
      return S_OK;
   }
};

A następnie klienta:

// evh_client.cpp
// compile with: /link /OPT:NOREF
#define _ATL_ATTRIBUTES 1
#include <atlbase.h>
#include <atlcom.h>
#include <stdio.h>
#include "evh_server.h"

[ module(name="EventReceiver") ];

[ event_receiver(com) ]
class CReceiver {
public:
   HRESULT MyHandler1(int nValue) {
      printf_s("MyHandler1 was called with value %d.\n", nValue);
      return S_OK;
   }

   HRESULT MyHandler2(int nValue) {
      printf_s("MyHandler2 was called with value %d.\n", nValue);
      return S_OK;
   }

   void HookEvent(IEventSource* pSource) {
      __hook(&IEvents::MyEvent, pSource, &CReceiver::MyHandler1);
      __hook(&IEvents::MyEvent, pSource, &CReceiver::MyHandler2);
   }

   void UnhookEvent(IEventSource* pSource) {
      __unhook(&IEvents::MyEvent, pSource, &CReceiver::MyHandler1);
      __unhook(&IEvents::MyEvent, pSource, &CReceiver::MyHandler2);
   }
};

int main() {
   // Create COM object
   CoInitialize(NULL);
   {
      IEventSource* pSource = 0;
      HRESULT hr = CoCreateInstance(__uuidof(CSource), NULL,         CLSCTX_ALL, __uuidof(IEventSource), (void **) &pSource);
      if (FAILED(hr)) {
         return -1;
      }

      // Create receiver and fire event
      CReceiver receiver;
      receiver.HookEvent(pSource);
      pSource->FireEvent();
      receiver.UnhookEvent(pSource);
   }
   CoUninitialize();
   return 0;
}

hdcxwbd5.collapse_all(pl-pl,VS.110).gifDane wyjściowe

MyHandler1 was called with value 123.
MyHandler2 was called with value 123.

Układ COM zależne zdarzenia

Zależność układ jest tylko kwestią programowania COM.W obsłudze zdarzeń macierzystych i zarządzanych podpisów (typ zwracany, konwencja wywołania i argumenty) programy obsługi muszą odpowiadać ich zdarzenia, ale nazwy obsługi nie muszą odpowiadać ich zdarzenia.

Jednakże, w obsłudze zdarzeń modelu COM, po ustawieniu layout_dependent parametr event_receiver do true, nazwisko i podpis, dopasowania jest wymuszane.Oznacza to, że nazwiska i wzory podpisów programów obsługi w przypadku gdy odbiorca musi dokładnie odpowiadać nazwiska i wzory podpisów zdarzenia, które są potrzebne.

Gdy layout_dependent jest ustawiona na false, wywołanie klasy Konwencji i składowania (wirtualne, statyczne i tak dalej) można mieszane i dopasowywane między wypalania metody zdarzeń i metod podczepiania (jego delegatów).Jest nieco bardziej efektywne, aby layout_dependent=true.

Załóżmy na przykład, IEventSource jest zdefiniowany w mają następujące metody:

[id(1)] HRESULT MyEvent1([in] int value);
[id(2)] HRESULT MyEvent2([in] int value);

Załóżmy, że źródło zdarzeń ma następującą postać:

[coclass, event_source(com)]
class CSource : public IEventSource {
public:
   __event __interface IEvents;

   HRESULT FireEvent() {
      MyEvent1(123);
      MyEvent2(123);
      return S_OK;
   }
};

Następnie, w naczyniu zbierającym zdarzenia, każdy program obsługi podłączony do metody w IEventSource musi odpowiadać jej nazwisko i podpis, w następujący sposób:

[coclass, event_receiver(com, true)]
class CReceiver {
public:
   HRESULT MyEvent1(int nValue) {  // name and signature matches MyEvent1
      ...
   }
   HRESULT MyEvent2(E c, char* pc) {  // signature doesn't match MyEvent2
      ...
   }
   HRESULT MyHandler1(int nValue) {  // name doesn't match MyEvent1 (or 2)
      ...
   }
   void HookEvent(IEventSource* pSource) {
      __hook(IFace, pSource);  // Hooks up all name-matched events 
                               // under layout_dependent = true
      __hook(&IFace::MyEvent1, pSource, &CReceive::MyEvent1);   // valid
      __hook(&IFace::MyEvent2, pSource, &CSink::MyEvent2);   // not valid
      __hook(&IFace::MyEvent1, pSource, &CSink:: MyHandler1); // not valid
   }
};

Zobacz też

Informacje

Obsługa zdarzeń