Deep parsing of events in C + + programs and event handling in COM _c language

Source: Internet
Author: User
Tags comments uuid

event handling in native C + +
when handling native C + + events, you set the event source and event sink separately using the event_source and event_receiver attributes, and specify Type=native. These attributes allow classes that apply them to fire and handle events in a native non-COM context.
declaring an event
in the event source class, you can declare the method as an event by using the __event keyword for a method declaration. Make sure that you declare the method, but do not define it; This will result in a compiler error because the compiler implicitly defines the method when it is converted to an event. A native event can be a method with 0 or more parameters. The return type can be void or any integral type.
Defining event Handlers
in the event receiver class, you define event handlers, which are methods that have signatures (return types, calling conventions, and parameters) that match the events they will handle.
Hook event handlers to events
also in the event receiver class, you can use internal functions __hook to associate an event with an event handler, and you can use __unhook to cancel an event's association with an event handler. You can hook up multiple events to an event handler, or hook multiple event handlers to an event.
Fire Event
to fire an event, simply invoke the method declared as an event in the event source class. If the handler is hooked to an event, the handler is invoked.
Native C + + event code
The following example shows how to fire events in native C + +. To compile and run this example, refer to the comments in the code.
Sample Code

Evh_native.cpp
#include <stdio.h>

[event_source (native)]
class Csource {public
:
  __ event void MyEvent (int nvalue);

[Event_receiver (native)]
Class Creceiver {public
:
  void MyHandler1 (int nvalue) {
   printf_s ("MyHandler1 is called with value%d.\n", Nvalue);
  }

  void MyHandler2 (int nvalue) {
   printf_s ("MyHandler2 is called with value%d.\n", Nvalue);
  }

  void Hookevent (csource* psource) {
   __hook (&csource::myevent, Psource, &creceiver::myhandler1);
   __hook (&csource::myevent, Psource, &creceiver::myhandler2);
  }

  void Unhookevent (csource* psource) {
   __unhook (&csource::myevent, Psource, &creceiver::myhandler1);
   __unhook (&csource::myevent, Psource, &creceiver::myhandler2);
  }
;

int main () {
  csource source;
  Creceiver receiver;

  Receiver.hookevent (&source);
  __raise source. MyEvent (123);
  Receiver.unhookevent (&source);
}

Output:

MyHandler2 is called with value 123.
MyHandler1 is called with value 123.

Event Handling in COM
in COM event handling, you use the event_source and event_receiver attributes to set the event source and event sink separately and specify type=com. These features inject the appropriate code into the custom interface, dispatch interface, and dual interface so that the classes that these interfaces can apply to fire events and handle events through COM connection points.
declaring events
In the event source class, use the __event keyword on the interface declaration to declare the method of the interface as an event. These events are fired when you call the event of this interface as an interface method. The method on the event interface can have 0 or more parameters (all in Parameters). The return type can be void or any integral type.
Defining an event handler
In the event receiver class, you can define event handlers, which are methods that have signatures (return types, calling conventions, and parameters) that match the events they will handle. For COM events, the calling convention does not have to match; For more information, see the COM events that are dependent on the layout later in this article.
Hook an event handler to an event
Also in the event receiver class, you can use an internal function __hook to associate an event with an event handler, and you can use __unhook to cancel the association of an event with an event handler. You can hook up multiple events to an event handler, or hook multiple event handlers to an event.
Attention
Typically, there are two ways to enable a COM event sink to access the event source interface definition. The first is to share a common header file, as shown below. The second is to use the #import in conjunction with the Embedded_idl import qualifier so that the event source type library is written to the. tlh file that retains the code generated by the attribute.
Firing events
To fire an event, simply call the method in the interface that is declared using the __event keyword in the event source class. If the handler is hooked to an event, the handler is invoked.
COM event code
The following example shows how to fire an event in a COM class. To compile and run this example, refer to the comments in the code.

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;

Next is the 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;
  }
;

And then the client:

Evh_client.cpp//compile with:/link/opt:noref #define _atl_attributes 1 #include <atlbase.h> #include <atl

com.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 WI
   Th value%d.\n ", nvalue);
  return S_OK;
   HRESULT MyHandler2 (int nvalue) {printf_s ("MyHandler2 is 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;

 }

Output

MyHandler1 is called with value 123.
MyHandler2 is called with value 123.

COM events that depend on the layout
layout dependencies are only one problem in COM programming. In native and managed event handling, the signature of the handler (the return type, calling convention, and parameters) must match the event, but the name of the handler does not have to match the event.
However, in COM event handling, if you set the event_receiver layout_dependent argument to True, the name and signature will be forced to match. This means that the name and signature of the handler in the event receiver must exactly match the name and signature of the event that the handler will hook up with.
When Layout_dependent is set to false, the calling convention and storage class (virtual, static, etc.) between the firing event method and the Hook method (its delegate) can be mixed and matched. The efficiency of setting layout_dependent to True is a little higher.
For example, suppose IEventSource is defined as having the following methods:

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

Assume that the event source has the following form:

[coclass, event_source (COM)]
Class Csource:public IEventSource {public
:
  __event __interface ievents;

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

In the event receiver, any handler for the method that hooks into IEventSource must match its name and signature, as follows:

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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.