Gestione degli eventi in COM

In gestione degli eventi COM, è stato impostato un'origine eventi e utilizzare un ricevitore di eventi un event_source e event_receiver attributi, rispettivamente, specificando type=COM.Questi attributi è invece possibile inserire il codice appropriato per personalizzata, inviano e interfacce duali consentono di classi a cui si applica per generare gli eventi e gestire eventi dai punti di connessione COM.

Dichiarazione di eventi

in una classe di origine evento, utilizzare __event parola chiave in una dichiarazione dell'interfaccia per dichiarare che i metodi di interfaccia come eventi.Gli eventi dell'interfaccia vengono generati quando vengono definite come metodi di interfaccia.Metodi nelle interfacce eventi possono contenere zero o più parametri (che se vengono in parametri).Il tipo restituito può essere void o un tipo integrale.

Definizione di gestori degli eventi

In una classe del ricevitore di eventi, definire i gestori eventi, ovvero metodi con firme (tipi restituiti, convenzioni di chiamata e argomenti) che corrispondono l'evento che gestiranno.Per eventi COM, convenzioni di chiamata non devono essere uguali; vedere Eventi dipendenti di layout COM in per i dettagli.

Hook dei gestori eventi agli eventi

Inoltre in una classe del ricevitore di eventi, utilizzare la funzione intrinseca __hook per associare gli eventi ai gestori eventi e __unhook per dissociare gli eventi dai gestori eventi.È possibile associare più eventi a un gestore eventi, o a diversi gestori eventi a un evento.

[!NOTA]

In genere, sono disponibili due tecniche per consentire un ricevitore di eventi COM alle definizioni di interfaccia di accesso di origine evento.Il primo, come mostrato di seguito, è di condividere un file di intestazione comune.il secondo è di utilizzare #import con embedded_idl importare il qualificatore, in modo che la libreria dei tipi di origine evento viene scritta nel file con estensione tlh con il codice attributo-generato mantenuto.

eventi di infornamento

Per generare un evento, è sufficiente chiamare un metodo nell'interfaccia dichiarata con __event classe di origine di parola chiave nell'evento.Se i gestori sono stati agganciati all'evento, i gestori verranno chiamati.

hdcxwbd5.collapse_all(it-it,VS.110).gifCodice dell'evento COM

Nell'esempio seguente viene illustrato come generare un evento in una classe COM.Per compilare ed eseguire l'esempio, fare riferimento ai commenti nel codice.

// 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;

Quindi il server:

// 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;
   }
};

Quindi il client:

// 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(it-it,VS.110).gifOutput

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

Eventi dipendenti di layout COM

La dipendenza del layout è solo un problema per la programmazione COM.In codice nativo e gestione degli eventi gestita, le firme (tipo restituito, convenzione di chiamata e argomenti) dei gestori devono corrispondere ai relativi eventi, ma i nomi del gestore eventi non devono corrispondere ai relativi eventi.

Tuttavia, nella gestione degli eventi COM, se si imposta layout_dependent parametro di event_receiver in true, il nome e il corrispondente della firma viene applicato.Ciò significa che i nomi e le firme del ricevitore dei gestori nel caso devono corrispondere esattamente ai nomi e le firme degli eventi ai quali vengono agganciati.

quando layout_dependent è impostato su false, la convenzione di chiamata e la classe di archiviazione (virtuale, statico, e così via) possono essere combinati e una corrispondenza tra il metodo dell'evento di infornamento e i metodi hook che consentono di (i delegati).È leggermente più efficiente disporre layout_dependent=true.

Si supponga, ad esempio IEventSource viene definito disporre dei seguenti metodi:

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

Si presupponga origine evento ha il formato seguente:

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

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

Quindi, nel ricevitore, qualsiasi gestore agganciato a un metodo in IEventSource deve corrispondere al nome e la stessa firma, come segue:

[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
   }
};

Vedere anche

Riferimenti

Gestione degli eventi