< Old To New C++ .Net version 4 | Main | Old To New C++ .Net version 6 >


 

 

Early Stages of the C++ .Net 27

(From Managed Extensions for C++ to new C++ .NET Syntax)

 

 

The code snippets used in this module if any are Visual C++ .Net 2003 dominated and if compiled using Visual C++ .Net 2005 you need to use the /clr:oldSyntax option). The following are the topics available in this module.

  1. The __event keyword

  2. Native Events

  3. COM Events

  4. Managed Events

  5. Example: Native Events

  6. Example: COM Events

  7. Example: Managed Events

  8. Managed Extensions for C++: __delegate Keyword

 

 

 

 

The __event keyword

 

This keyword declares an event. The syntaxes are:

  1. __event method-declarator;

  2. __event __interface interface-specifier;

  3. __event member-declarator;

The keyword __event can be applied to a method declaration, an interface declaration, or a data member declaration. Depending on whether your event source and receiver are native C++, COM, or managed (.NET Framework), you can use the following constructs as events:

 

Native C++

COM

Managed (.NET Framework)

method

method

interface

data member

 

Table 4

 

Use __hook in an event receiver to associate a handler method with an event method. Note that after you create an event with the __event keyword, all event handlers subsequently hooked to that event will be called when the event is called. An __event method declaration cannot have a definition; a definition is implicitly generated, so the event method can be called as if it were any ordinary method.

 

Native Events

 

Native events are methods. The return type is typically HRESULT or void, but can be any integral type, including an enum. When an event uses an integral return type, an error condition is defined when an event handler returns a nonzero value, in which case the event being raised will call the other delegates.

// Examples of native C++ events:

__event void OnDblClick();

__event HRESULT OnClick(int* b, char* s);

COM Events

 

Component Object Model (COM) events are interfaces. The parameters of a method in an event source interface should be in parameters (but this is not rigorously enforced), because an out parameter is not useful when multicasting. A level 1 warning will be issued if you use an out parameter. The return type is typically HRESULT or void, but can be any integral type, including enum. When an event uses an integral return type and an event handler returns a nonzero value, it is an error condition, in which case the event being raised aborts calls to the other delegates. Note that the compiler will automatically mark an event source interface as a source in the generated IDL. The __interface keyword is always required after __event for a COM event source.

// Example of a COM event:

__event __interface IEvent1;

Managed Events

 

Managed events are data members or methods. When used with an event, the return type of a delegate must be compliant with the Common Language Specification (CLS). The return type of the event handler must match the return type of the delegate. If a managed event is a data member, its type must be a pointer to a delegate. In the .NET Framework, you can treat a data member as if it were a method itself (that is, the Invoke method of its corresponding delegate). You must predefine the delegate type for declaring a managed event data member. In contrast, a managed event method implicitly defines the corresponding managed delegate if it is not already defined. For example, you can declare an event value such as OnClick as an event as follows:

// Examples of managed events:

__event ClickEventHandler* OnClick;  // data member as event

__event void OnClick(String* s);  // method as event

When implicitly declaring a managed event, you can specify add and remove accessors that will be called when event handlers are added or removed. You can also define the method that calls (raises) the event from outside the class.

 

Example: Native Events

// Event handling, the native event

// compile with: /c

[event_source(native)]

class CSource

{

    public:

        __event void MyEvent(int nValue);

};

Example: COM Events

// Event handling, the COM event

// compile with: /c

#define _ATL_ATTRIBUTES 1

#include <atlbase.h>

#include <atlcom.h>

 

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

 

[ dual, uuid("00000000-0000-0000-0000-000000000002") ]

__interface IEventSource {

   [id(1)] HRESULT MyEvent();

};

[ coclass, uuid("00000000-0000-0000-0000-000000000003"),  event_source(com) ]

class CSource : public IEventSource

{

public:

   __event __interface IEventSource;

   HRESULT FireEvent() {

      __raise MyEvent();

      return S_OK;

   }

};

Example: Managed Events

// Event handling, the managed event

// compile with: /clr:oldSyntax /c

using namespace System;

[event_source(managed)]

public __gc class CPSource

{

public:

   __event void MyEvent(Int16 nValue);

};

When applying an attribute to an event, you can specify that the attribute apply to either the generated methods or to the Invoke method of the generated delegate. The default (event:) is to apply the attribute to the event.

 

// Event handling the managed event

// compile with: /clr:oldSyntax /c

using namespace System;

[attribute(All, AllowMultiple=true)]

public __gc class Attr {};

 

public __delegate void D();

 

public __gc class X {

public:

   [method:Attr] __event D* E;

   [returnvalue:Attr] __event void noE();

};

 

Managed Extensions for C++: __delegate Keyword

 

This topic applies only to version 1 of Managed Extensions for C++. This syntax should only be used to maintain version 1 code. Use delegate for the equivalent functionality in the new syntax. The __delegate defines a reference type that can be used to encapsulate a method with a specific signature. The syntax is:

__delegate function-declarator

A delegate is roughly equivalent to a C++ function pointer except for the following difference: a delegate can only be bound to one or more methods within a __gc class. When the compiler encounters the __delegate keyword, a definition of a __gc class is generated. This __gc class has the following characteristics:

  1. It inherits from System::MulticastDelegate.

  2. It has a constructor that takes two arguments: a pointer to a __gc class or NULL (in the case of binding to a static method) and a fully qualified method of the specified type.

  3. It has a method called Invoke, whose signature matches the declared signature of the delegate.

In the following example, a __gc class (MyCalendar) and a delegate (GetDayOfWeek) are declared. The delegate is then bound to the different methods of MyCalendar, invoking each in turn:

// Test.cpp : main project file.

// keyword delegate

// compile with: /clr:oldSyntax

#include "stdafx.h"

 

using namespace System;

 

#using <mscorlib.dll>

using namespace System;

 

__delegate int GetDayOfWeek();

__gc class MyCalendar

{

      public:

            MyCalendar() : m_nDayOfWeek(4) {}

            int MyGetDayOfWeek()

            {

                  Console::WriteLine("just a handler...");

                  return m_nDayOfWeek;

            }

            static int MyStaticGetDayOfWeek()

            {

                  Console::WriteLine("a static handler...");

                  return 6;

            }

      private:

            int m_nDayOfWeek;

};

 

int main ()

{

      // declare delegate type

      GetDayOfWeek * pGetDayOfWeek;

      int nDayOfWeek;

      // bind delegate to static method

      pGetDayOfWeek = new GetDayOfWeek(0, &MyCalendar::MyStaticGetDayOfWeek);

      nDayOfWeek = pGetDayOfWeek->Invoke();

      Console::WriteLine(nDayOfWeek);

      // bind delegate to instance method

      MyCalendar * pcal = new MyCalendar();

      pGetDayOfWeek = static_cast<GetDayOfWeek*>(Delegate::Combine(pGetDayOfWeek,

            new GetDayOfWeek(pcal, &MyCalendar::MyGetDayOfWeek)));

      nDayOfWeek = pGetDayOfWeek->Invoke();

      Console::WriteLine(nDayOfWeek);

      // delegate now bound to two methods; remove instance method

      pGetDayOfWeek = static_cast<GetDayOfWeek*>(Delegate::Remove(pGetDayOfWeek,

            new GetDayOfWeek(pcal, &MyCalendar::MyGetDayOfWeek)));

 

      return 0;

}

Output:

__delegate, gc, new keywords program output

 

 

Part 1 | Part 2 | Part 3 | Part 4 | Part 5 | Part 6 | Part 7 | Part 8 | Part 9

 


 

< Old To New C++ .Net version 4 | Main | Old To New C++ .Net version 6 >