Поделиться через


Обработка событий в модели COM

В событии при обработке модели COM, настроенными помощью приемников источника события и события event_source и event_receiver атрибуты, соответственно, указав type=com.Эти атрибуты впрыскивают надлежащего кода для пользовательского, посылают и сдвоенные интерфейсы для классов, к которым они применяются, чтобы создать события и обработка событий через точки подключения модели COM.

Объявление событий

В классе источника событий, воспользуйтесь __event ключевое слово для объявления интерфейса, чтобы объявить как методы интерфейса события.События этого интерфейса предоставлены при вызове их как методы интерфейса.Методы в интерфейсах события могут иметь ноль и более параметров (которые если все IN параметры).Возвращаемым типом может быть пустой или любой целочисленный тип.

Определение обработчиков событий

В классе приемника событий задаются обработчики событий, методы с подписями (возвращаемыми типами, вызов соглашения и аргументы), которые соответствуют событие, они обрабатывают.Для событий модели COM, вызов соглашения соответствовать; см. События модели COM структуры зависимые для под подробными сведениями.

Циклический обработчики событий на события

Также в классе приемника событий, используйте функцию внутреннеприсущую __hook связывание с обработчиками событий и событий __unhook разъединить события из обработчиков событий.Можно обработчик несколько событий к обработчику событий или нескольких обработчиков событий к событию.

ПримечаниеПримечание

Обычно 2 метода, чтобы позволить приемник событий модели COM к определениям интерфейса-источника событий доступа.Во-первых, как показано ниже, совместно использовать общий файл заголовка.Второе использование #import с embedded_idl квалификатор, чтобы импортировать библиотеку типов источника события будет записывается в файл с атрибут-произведенный .tlh сохраненного кода.

События включения

Чтобы создать событие, просто вызовите метод в интерфейсе, объявленном __event класс источника ключевого слова в случае., Если обработчики были закреплены к событию, обработчики будут вызваны.

hdcxwbd5.collapse_all(ru-ru,VS.110).gifКод события модели COM

В следующем примере показано, как создать событие в COM-класс.Чтобы компилировать и запуск примера см. в разделе комментариев в коде.

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

Затем сервер:

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

Затем клиент:

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

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

События модели COM структуры зависимые

Зависимость структуры только проблемой для программирования модели COM.В собственном и управляемом обработке событий, подписи (возвращаемый тип, соглашением о вызове и аргументы) должны совпадать их обработчики события, но не должны совпадать их имена обработчиков событий.

Однако в событии модели COM, когда задается при обработке layout_dependent параметр event_receiver В trueимя и соответствовать подписи применяются.Это означает, что имена и подписи приемников обработчиков в случае должны точно соответствовать именам и сигнатурам событий, к которым они закреплены.

После layout_dependent равно falseсоглашение о вызовах, и класс хранения (виртуальный, статическое и т д) могут быть смешанны и соответствующие между методом события включения и циклических методами (его делегатами).Он немного более эффективным иметь layout_dependent=true.

Например, предположим IEventSource определяет, чтобы иметь следующие методы:

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

Предположим, что источник событий имеет следующую форму:

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

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

Затем в случае любой приемник обработчик закрепленный методу in IEventSource соответствовать своим именем и сигнатурой, следующим образом:

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

См. также

Ссылки

Обработка событий