이벤트 처리에 대 한 COM

COM에서 이벤트 처리를 사용 하 여 이벤트 소스와 이벤트 수신기를 설정 하 여 해당 event_sourceevent_receiver 각각 지정 특성 type=com.이들이 특성은 적절 한 코드를 사용자 지정, 디스패치 및 이중 인터페이스의 클래스는 COM 연결 지점을 통해 이벤트를 처리 하 고 이벤트 적용 삽입 합니다.

이벤트 선언

이벤트 소스 클래스에서 사용 하는 __event 키워드에는 해당 인터페이스의 메서드를 이벤트로 선언 하는 인터페이스 선언입니다.해당 인터페이스의 이벤트를 해당 인터페이스 메서드로 호출 시 발생 합니다.이벤트 인터페이스의 메서드는 0 개 이상의 매개 변수가 있을 수 있습니다 (모두 해야 하는 에서 매개 변수)입니다.반환 형식은 void 또는 모든 정수 계열 형식이 될 수 있습니다.

이벤트 처리기 정의

이벤트 수신기 클래스에서 처리 하려는 이벤트와 시그니처 (반환 형식, 호출 규칙 및 인수) 메서드는 이벤트 처리기를 정의 합니다.COM 이벤트에 대 한 호출 규칙이 일치 하지 않아도 됩니다. 참조 하십시오 레이아웃 종속 COM 이벤트 아래의 세부 사항에 대 한.

이벤트에 이벤트 처리기 후크

또한 이벤트 수신기 클래스에서 내장 함수를 사용 하면 __hook 이벤트와 이벤트 처리기를 연결 하 고 __unhook 이벤트 처리기에서 이벤트 연결을 해제 하려면.이벤트 처리기에 여러 이벤트 또는 여러 이벤트 처리기를 이벤트에 연결할 수 있습니다.

[!참고]

일반적으로 COM 이벤트 수신기에서 이벤트 소스 인터페이스 정의 액세스할 수 있도록 하는 두 가지 방법입니다.첫째, 아래와 같이 공용 헤더 파일을 공유할 것입니다.두 번째 사용 하는 것 # importembedded_idl 이벤트 원본 형식 라이브러리 특성으로 생성 된 코드와 보존.tlh 파일에 쓸 수 없도록 한정자를 가져옵니다.

이벤트를 발생 시키는

이벤트를 발생 시키는 메서드를 선언 하는 인터페이스에 호출 하기만 하면 됩니다 있는 __event 키워드는 이벤트 원본 클래스입니다.처리기가 이벤트에 후크된 경우 처리기가 호출 됩니다.

hdcxwbd5.collapse_all(ko-kr,VS.110).gifCOM 이벤트 코드

다음 예제는 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(ko-kr,VS.110).gifOutput

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

레이아웃 종속 COM 이벤트

레이아웃 종속 COM 프로그래밍에만 있는 문제입니다.네이티브 및 관리 되는 이벤트 처리를 해당 이벤트 처리기의 시그니처 (반환 형식, 호출 규칙 및 인수)과 일치 해야 하지만 처리기 이름은 이벤트와 일치할 필요는 없습니다.

그러나 설정할 때 COM 이벤트 처리에 layout_dependent 매개 변수를 event_receivertrue, 이름 및 시그니처가 일치 하는 적용.이벤트 이름 및 시그니처를 연결 된 이벤트의 수신기 정확 하 게 일치 해야 합니다 이름 및 시그니처는 처리기의 따라서.

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

이벤트 수신기에서 처리기 후크 다음 메서드를 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
   }
};

참고 항목

참조

이벤트 처리