__event and __delegate question

J

Joe Thompson

Hi,

I am using VC++.Net 2003 with WinForms to write a serial port application.
I downloaded the newest VC++ examples from MSDN and found a project called
Using the COM Port. In it, there is a class called Rs232. It has three
lines of code:

// These events allow the program using this class to react to Comm Port
events.

__event DataReceived(Rs232* Source, Byte DataBuffer[]);

__event TxCompleted(Rs232* Source);

__event CommEvent(Rs232* Source, EventMasks* Mask);


In the example program a timer fires every 200 ms and reads from the port.
I would rather have an event fire and tell me there is data ready. It lloks
to me like that is possible with this class. I've included the Rs232.h file
in my Form1.h file. I don't understand this __event and __delegate stuff
and am looking for some help here. What methods do I need to write? What
should they look like? Where should I put them?

Thank you,
Joe
 
E

Edward Diener

Joe said:
Hi,

I am using VC++.Net 2003 with WinForms to write a serial port
application. I downloaded the newest VC++ examples from MSDN and
found a project called Using the COM Port. In it, there is a class
called Rs232. It has three lines of code:

// These events allow the program using this class to react to Comm
Port events.

__event DataReceived(Rs232* Source, Byte DataBuffer[]);

__event TxCompleted(Rs232* Source);

__event CommEvent(Rs232* Source, EventMasks* Mask);


In the example program a timer fires every 200 ms and reads from the
port. I would rather have an event fire and tell me there is data
ready. It lloks to me like that is possible with this class. I've
included the Rs232.h file in my Form1.h file. I don't understand
this __event and __delegate stuff and am looking for some help here.
What methods do I need to write? What should they look like? Where
should I put them?

The __events you see above mean that the Rs232 class is going to trigger
events when something happens. I think you have left out a return value on
the __event but it is always 'void' anyway. In order to have your form
handle an event, you create a handler member function in your form's class
with the same signature as an __event but without the __event keyword. You
then can hook your event handler to the event so that when the event is
triggered, your member function gets called. What you are doing is hooking
your event handler to both the event and a particular object of the class
which is generating the __event. In order to hook your event handler, look
at the documentation for the __hook keyword and how it is used.

As an example for the DataReceived event:

1) Add a member function to your form class with the signature: "void
MyHandler(Rs232* Source, Byte DataBuffer[]);". Implement this function to
handle the event as you see fit.

2) Instanatiate the Rs232 object somewhere in your form class. We will call
the pointer "Rs232ObjectPointer".

3) When you want to handle the DataReceived event from the instantiated
Rs232 object, your code in one of your form's member functions would be:
__hook(Rs232::DataReceived, Rs232ObjectPointer,MyForm::MyHandler);

4) When you no longer want to handle the event, your code would
be:__unhook(Rs232::DataReceived, Rs232ObjectPointer,MyForm::MyHandler);

OK, that is for this event. If the event itself is specified through a
delegate, then you have to create a delegate which points to your event
handler and use the += syntax to add your event handler to the list of event
handlers for the event ( equivalent of __hook ) and use the -= syntax to
remove your event handler from the list of event handlers for the event.

As an example, imagine that the __event signature for the DataReceived event
was actually:

__delegate void DataReceivedDelegate(Rs232* Source, Byte DataBuffer[]); //
outside the Rs232 class

__event DataReceivedDelegate * DataReceived; // inside the Rs232 class

Now do steps 1) and 2) above but for step 3 and 4 we now have:

3) When you want to handle the DataReceived event from the instantiated
Rs232 object, your code in one of your form's member functions would be:

DataReceivedDelegate * drg = new
DataReceivedDelegate(this,MyForm::MyHandler);
Rs232ObjectPointer -> DataReceived += drg;

4) When you no longer want to handle the event, your code would be:
Rs232ObjectPointer -> DataReceived -= drg;

I will heartily recommend that you read the MSDN documentation of delegates
and events and, if you still find things confusing and you have the money to
spend, get Richard Grimes book "Programming with Managed Extensions for
Visual C++ .NET". The latter has inside information on nearly everything you
will ever think to ask about MC++, along with delegates and events.
 
J

Joe Thompson

Hi Edward,

Thank you for your detailed reply. I tried adding a handler like this:

public __gc class Form1 : public System::Windows::Forms::Form
{
private:

Rs232* m_CommPort;

public:

Form1(void)
{

InitializeComponent();
m_CommPort = new Rs232;
__hook(Rs232::DataReceived, m_CommPort,
Form1::DataReceivedHandler);
}

public:

void DataReceivedHandler(Rs232* Source, Byte DataBuffer[])
{
// do something here
}



but keep getting a compiler error on the __hook line (error C3709:
'Rs232::DataReceived': improper syntax for specifying event in
__hook/__unhook). The documentation looks the same as you explained. I
noticed that the documentation and examples all have 2 classes involved -
source and handler and then a program. Can't my form contain the handler?
You mentioned that I may have forgot the "void" in the event but that is
copied straight from the class. I would really appreciate if you could look
into this class (Rs232) if you have some time. I am really getting
frustrated with serial port access in .net.

Thanks again,
Joe

Edward Diener said:
Joe said:
Hi,

I am using VC++.Net 2003 with WinForms to write a serial port
application. I downloaded the newest VC++ examples from MSDN and
found a project called Using the COM Port. In it, there is a class
called Rs232. It has three lines of code:

// These events allow the program using this class to react to Comm
Port events.

__event DataReceived(Rs232* Source, Byte DataBuffer[]);

__event TxCompleted(Rs232* Source);

__event CommEvent(Rs232* Source, EventMasks* Mask);


In the example program a timer fires every 200 ms and reads from the
port. I would rather have an event fire and tell me there is data
ready. It lloks to me like that is possible with this class. I've
included the Rs232.h file in my Form1.h file. I don't understand
this __event and __delegate stuff and am looking for some help here.
What methods do I need to write? What should they look like? Where
should I put them?

The __events you see above mean that the Rs232 class is going to trigger
events when something happens. I think you have left out a return value on
the __event but it is always 'void' anyway. In order to have your form
handle an event, you create a handler member function in your form's class
with the same signature as an __event but without the __event keyword. You
then can hook your event handler to the event so that when the event is
triggered, your member function gets called. What you are doing is hooking
your event handler to both the event and a particular object of the class
which is generating the __event. In order to hook your event handler, look
at the documentation for the __hook keyword and how it is used.

As an example for the DataReceived event:

1) Add a member function to your form class with the signature: "void
MyHandler(Rs232* Source, Byte DataBuffer[]);". Implement this function to
handle the event as you see fit.

2) Instanatiate the Rs232 object somewhere in your form class. We will call
the pointer "Rs232ObjectPointer".

3) When you want to handle the DataReceived event from the instantiated
Rs232 object, your code in one of your form's member functions would be:
__hook(Rs232::DataReceived, Rs232ObjectPointer,MyForm::MyHandler);

4) When you no longer want to handle the event, your code would
be:__unhook(Rs232::DataReceived, Rs232ObjectPointer,MyForm::MyHandler);

OK, that is for this event. If the event itself is specified through a
delegate, then you have to create a delegate which points to your event
handler and use the += syntax to add your event handler to the list of event
handlers for the event ( equivalent of __hook ) and use the -= syntax to
remove your event handler from the list of event handlers for the event.

As an example, imagine that the __event signature for the DataReceived event
was actually:

__delegate void DataReceivedDelegate(Rs232* Source, Byte DataBuffer[]); //
outside the Rs232 class

__event DataReceivedDelegate * DataReceived; // inside the Rs232 class

Now do steps 1) and 2) above but for step 3 and 4 we now have:

3) When you want to handle the DataReceived event from the instantiated
Rs232 object, your code in one of your form's member functions would be:

DataReceivedDelegate * drg = new
DataReceivedDelegate(this,MyForm::MyHandler);
Rs232ObjectPointer -> DataReceived += drg;

4) When you no longer want to handle the event, your code would be:
Rs232ObjectPointer -> DataReceived -= drg;

I will heartily recommend that you read the MSDN documentation of delegates
and events and, if you still find things confusing and you have the money to
spend, get Richard Grimes book "Programming with Managed Extensions for
Visual C++ .NET". The latter has inside information on nearly everything you
will ever think to ask about MC++, along with delegates and events.
 
E

Edward Diener

Joe said:
Hi Edward,

Thank you for your detailed reply. I tried adding a handler like
this:

public __gc class Form1 : public System::Windows::Forms::Form
{
private:

Rs232* m_CommPort;

public:

Form1(void)
{

InitializeComponent();
m_CommPort = new Rs232;
__hook(Rs232::DataReceived, m_CommPort,
Form1::DataReceivedHandler);
}

public:

void DataReceivedHandler(Rs232* Source, Byte DataBuffer[])
{
// do something here
}



but keep getting a compiler error on the __hook line (error C3709:
'Rs232::DataReceived': improper syntax for specifying event in
__hook/__unhook).

My fault in the explanation. Try

__hook(&Rs232::DataReceived, m_CommPort, &Form1::DataReceivedHandler);

instead. The address-of operator may be needed. At least that is what the
doc on __hook and __unhook shows.
The documentation looks the same as you explained.
I noticed that the documentation and examples all have 2 classes
involved - source and handler and then a program. Can't my form
contain the handler? You mentioned that I may have forgot the "void"
in the event but that is copied straight from the class. I would
really appreciate if you could look into this class (Rs232) if you
have some time. I am really getting frustrated with serial port
access in .net.

Thanks again,
Joe

Edward Diener said:
Joe said:
Hi,

I am using VC++.Net 2003 with WinForms to write a serial port
application. I downloaded the newest VC++ examples from MSDN and
found a project called Using the COM Port. In it, there is a class
called Rs232. It has three lines of code:

// These events allow the program using this class to react to Comm
Port events.

__event DataReceived(Rs232* Source, Byte DataBuffer[]);

__event TxCompleted(Rs232* Source);

__event CommEvent(Rs232* Source, EventMasks* Mask);


In the example program a timer fires every 200 ms and reads from the
port. I would rather have an event fire and tell me there is data
ready. It lloks to me like that is possible with this class. I've
included the Rs232.h file in my Form1.h file. I don't understand
this __event and __delegate stuff and am looking for some help here.
What methods do I need to write? What should they look like? Where
should I put them?

The __events you see above mean that the Rs232 class is going to
trigger events when something happens. I think you have left out a
return value on the __event but it is always 'void' anyway. In order
to have your form handle an event, you create a handler member
function in your form's class with the same signature as an __event
but without the __event keyword. You then can hook your event
handler to the event so that when the event is triggered, your
member function gets called. What you are doing is hooking your
event handler to both the event and a particular object of the class
which is generating the __event. In order to hook your event
handler, look at the documentation for the __hook keyword and how it
is used.

As an example for the DataReceived event:

1) Add a member function to your form class with the signature: "void
MyHandler(Rs232* Source, Byte DataBuffer[]);". Implement this
function to handle the event as you see fit.

2) Instanatiate the Rs232 object somewhere in your form class. We
will call the pointer "Rs232ObjectPointer".

3) When you want to handle the DataReceived event from the
instantiated Rs232 object, your code in one of your form's member
functions would be: __hook(Rs232::DataReceived,
Rs232ObjectPointer,MyForm::MyHandler);

4) When you no longer want to handle the event, your code would
be:__unhook(Rs232::DataReceived,
Rs232ObjectPointer,MyForm::MyHandler);

OK, that is for this event. If the event itself is specified through
a delegate, then you have to create a delegate which points to your
event handler and use the += syntax to add your event handler to the
list of event handlers for the event ( equivalent of __hook ) and
use the -= syntax to remove your event handler from the list of
event handlers for the event.

As an example, imagine that the __event signature for the
DataReceived event was actually:

__delegate void DataReceivedDelegate(Rs232* Source, Byte
DataBuffer[]); // outside the Rs232 class

__event DataReceivedDelegate * DataReceived; // inside the Rs232
class

Now do steps 1) and 2) above but for step 3 and 4 we now have:

3) When you want to handle the DataReceived event from the
instantiated Rs232 object, your code in one of your form's member
functions would be:

DataReceivedDelegate * drg = new
DataReceivedDelegate(this,MyForm::MyHandler);
Rs232ObjectPointer -> DataReceived += drg;

4) When you no longer want to handle the event, your code would be:
Rs232ObjectPointer -> DataReceived -= drg;

I will heartily recommend that you read the MSDN documentation of
delegates and events and, if you still find things confusing and you
have the money to spend, get Richard Grimes book "Programming with
Managed Extensions for Visual C++ .NET". The latter has inside
information on nearly everything you will ever think to ask about
MC++, along with delegates and events.
 
J

Joe Thompson

Hi Edward,

That was the problem. I don't know how you can read that stuff but I'm sure
glad. I also had to change my return type to int instead of void on the
handler. I really appreciate your help. By the way, I am coming from
Borland C++ Builder and read your posts there quite often. I still think
VC++.net has a ways to go before being as easy to use but maybe that's just
because I'm used to Borland. I really don't like how everything is in the
..h files.

Thanks again,
Joe

Edward Diener said:
Joe said:
Hi Edward,

Thank you for your detailed reply. I tried adding a handler like
this:

public __gc class Form1 : public System::Windows::Forms::Form
{
private:

Rs232* m_CommPort;

public:

Form1(void)
{

InitializeComponent();
m_CommPort = new Rs232;
__hook(Rs232::DataReceived, m_CommPort,
Form1::DataReceivedHandler);
}

public:

void DataReceivedHandler(Rs232* Source, Byte DataBuffer[])
{
// do something here
}



but keep getting a compiler error on the __hook line (error C3709:
'Rs232::DataReceived': improper syntax for specifying event in
__hook/__unhook).

My fault in the explanation. Try

__hook(&Rs232::DataReceived, m_CommPort, &Form1::DataReceivedHandler);

instead. The address-of operator may be needed. At least that is what the
doc on __hook and __unhook shows.
The documentation looks the same as you explained.
I noticed that the documentation and examples all have 2 classes
involved - source and handler and then a program. Can't my form
contain the handler? You mentioned that I may have forgot the "void"
in the event but that is copied straight from the class. I would
really appreciate if you could look into this class (Rs232) if you
have some time. I am really getting frustrated with serial port
access in .net.

Thanks again,
Joe

Edward Diener said:
Joe Thompson wrote:
Hi,

I am using VC++.Net 2003 with WinForms to write a serial port
application. I downloaded the newest VC++ examples from MSDN and
found a project called Using the COM Port. In it, there is a class
called Rs232. It has three lines of code:

// These events allow the program using this class to react to Comm
Port events.

__event DataReceived(Rs232* Source, Byte DataBuffer[]);

__event TxCompleted(Rs232* Source);

__event CommEvent(Rs232* Source, EventMasks* Mask);


In the example program a timer fires every 200 ms and reads from the
port. I would rather have an event fire and tell me there is data
ready. It lloks to me like that is possible with this class. I've
included the Rs232.h file in my Form1.h file. I don't understand
this __event and __delegate stuff and am looking for some help here.
What methods do I need to write? What should they look like? Where
should I put them?

The __events you see above mean that the Rs232 class is going to
trigger events when something happens. I think you have left out a
return value on the __event but it is always 'void' anyway. In order
to have your form handle an event, you create a handler member
function in your form's class with the same signature as an __event
but without the __event keyword. You then can hook your event
handler to the event so that when the event is triggered, your
member function gets called. What you are doing is hooking your
event handler to both the event and a particular object of the class
which is generating the __event. In order to hook your event
handler, look at the documentation for the __hook keyword and how it
is used.

As an example for the DataReceived event:

1) Add a member function to your form class with the signature: "void
MyHandler(Rs232* Source, Byte DataBuffer[]);". Implement this
function to handle the event as you see fit.

2) Instanatiate the Rs232 object somewhere in your form class. We
will call the pointer "Rs232ObjectPointer".

3) When you want to handle the DataReceived event from the
instantiated Rs232 object, your code in one of your form's member
functions would be: __hook(Rs232::DataReceived,
Rs232ObjectPointer,MyForm::MyHandler);

4) When you no longer want to handle the event, your code would
be:__unhook(Rs232::DataReceived,
Rs232ObjectPointer,MyForm::MyHandler);

OK, that is for this event. If the event itself is specified through
a delegate, then you have to create a delegate which points to your
event handler and use the += syntax to add your event handler to the
list of event handlers for the event ( equivalent of __hook ) and
use the -= syntax to remove your event handler from the list of
event handlers for the event.

As an example, imagine that the __event signature for the
DataReceived event was actually:

__delegate void DataReceivedDelegate(Rs232* Source, Byte
DataBuffer[]); // outside the Rs232 class

__event DataReceivedDelegate * DataReceived; // inside the Rs232
class

Now do steps 1) and 2) above but for step 3 and 4 we now have:

3) When you want to handle the DataReceived event from the
instantiated Rs232 object, your code in one of your form's member
functions would be:

DataReceivedDelegate * drg = new
DataReceivedDelegate(this,MyForm::MyHandler);
Rs232ObjectPointer -> DataReceived += drg;

4) When you no longer want to handle the event, your code would be:
Rs232ObjectPointer -> DataReceived -= drg;

I will heartily recommend that you read the MSDN documentation of
delegates and events and, if you still find things confusing and you
have the money to spend, get Richard Grimes book "Programming with
Managed Extensions for Visual C++ .NET". The latter has inside
information on nearly everything you will ever think to ask about
MC++, along with delegates and events.
 
E

Edward Diener

Joe said:
Hi Edward,

That was the problem. I don't know how you can read that stuff but
I'm sure glad.

Glad to know it is working now.
I also had to change my return type to int instead of
void on the handler. I really appreciate your help. By the way, I
am coming from Borland C++ Builder and read your posts there quite
often. I still think VC++.net has a ways to go before being as easy
to use but maybe that's just because I'm used to Borland.

Think of __delegate as being equivalent to the C++ Builder __closure, but
with more power ( multi-casting, delegating to static/global functions ) and
therefore less ease of programming use. The __event keyword is essentially a
form of __delegate creator/manipulator to make connecting an event handler
to event sources easy to do.
I really
don't like how everything is in the .h files.

You can move your member function code to the .cpp files and VC++ .NET will
pick it up fine. It is annoying that all the internal wizards work on the
header files but remember that C#, MS's preferred language, has no concept
of source/header files and puts all code in a .cs file with all member
function code in the class definition. This is, of course, the way Java does
it also.
Thanks again,
Joe

Edward Diener said:
Joe said:
Hi Edward,

Thank you for your detailed reply. I tried adding a handler like
this:

public __gc class Form1 : public System::Windows::Forms::Form
{
private:

Rs232* m_CommPort;

public:

Form1(void)
{

InitializeComponent();
m_CommPort = new Rs232;
__hook(Rs232::DataReceived, m_CommPort,
Form1::DataReceivedHandler);
}

public:

void DataReceivedHandler(Rs232* Source, Byte DataBuffer[])
{
// do something here
}



but keep getting a compiler error on the __hook line (error C3709:
'Rs232::DataReceived': improper syntax for specifying event in
__hook/__unhook).

My fault in the explanation. Try

__hook(&Rs232::DataReceived, m_CommPort,
&Form1::DataReceivedHandler);

instead. The address-of operator may be needed. At least that is
what the doc on __hook and __unhook shows.
The documentation looks the same as you explained.
I noticed that the documentation and examples all have 2 classes
involved - source and handler and then a program. Can't my form
contain the handler? You mentioned that I may have forgot the "void"
in the event but that is copied straight from the class. I would
really appreciate if you could look into this class (Rs232) if you
have some time. I am really getting frustrated with serial port
access in .net.

Thanks again,
Joe

Joe Thompson wrote:
Hi,

I am using VC++.Net 2003 with WinForms to write a serial port
application. I downloaded the newest VC++ examples from MSDN and
found a project called Using the COM Port. In it, there is a
class called Rs232. It has three lines of code:

// These events allow the program using this class to react to
Comm Port events.

__event DataReceived(Rs232* Source, Byte DataBuffer[]);

__event TxCompleted(Rs232* Source);

__event CommEvent(Rs232* Source, EventMasks* Mask);


In the example program a timer fires every 200 ms and reads from
the port. I would rather have an event fire and tell me there is
data ready. It lloks to me like that is possible with this
class. I've included the Rs232.h file in my Form1.h file. I
don't understand this __event and __delegate stuff and am looking
for some help here. What methods do I need to write? What should
they look like? Where should I put them?

The __events you see above mean that the Rs232 class is going to
trigger events when something happens. I think you have left out a
return value on the __event but it is always 'void' anyway. In
order to have your form handle an event, you create a handler
member function in your form's class with the same signature as an
__event but without the __event keyword. You then can hook your
event handler to the event so that when the event is triggered,
your member function gets called. What you are doing is hooking
your event handler to both the event and a particular object of
the class which is generating the __event. In order to hook your
event handler, look at the documentation for the __hook keyword
and how it is used.

As an example for the DataReceived event:

1) Add a member function to your form class with the signature:
"void MyHandler(Rs232* Source, Byte DataBuffer[]);". Implement this
function to handle the event as you see fit.

2) Instanatiate the Rs232 object somewhere in your form class. We
will call the pointer "Rs232ObjectPointer".

3) When you want to handle the DataReceived event from the
instantiated Rs232 object, your code in one of your form's member
functions would be: __hook(Rs232::DataReceived,
Rs232ObjectPointer,MyForm::MyHandler);

4) When you no longer want to handle the event, your code would
be:__unhook(Rs232::DataReceived,
Rs232ObjectPointer,MyForm::MyHandler);

OK, that is for this event. If the event itself is specified
through a delegate, then you have to create a delegate which
points to your event handler and use the += syntax to add your
event handler to the list of event handlers for the event (
equivalent of __hook ) and use the -= syntax to remove your event
handler from the list of event handlers for the event.

As an example, imagine that the __event signature for the
DataReceived event was actually:

__delegate void DataReceivedDelegate(Rs232* Source, Byte
DataBuffer[]); // outside the Rs232 class

__event DataReceivedDelegate * DataReceived; // inside the Rs232
class

Now do steps 1) and 2) above but for step 3 and 4 we now have:

3) When you want to handle the DataReceived event from the
instantiated Rs232 object, your code in one of your form's member
functions would be:

DataReceivedDelegate * drg = new
DataReceivedDelegate(this,MyForm::MyHandler);
Rs232ObjectPointer -> DataReceived += drg;

4) When you no longer want to handle the event, your code would be:
Rs232ObjectPointer -> DataReceived -= drg;

I will heartily recommend that you read the MSDN documentation of
delegates and events and, if you still find things confusing and
you have the money to spend, get Richard Grimes book "Programming
with Managed Extensions for Visual C++ .NET". The latter has inside
information on nearly everything you will ever think to ask about
MC++, along with delegates and events.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top