# Message Actions

All the code under the MessageActions item in the original Open Text Team Developer application is ported to an event handler function named using the same naming convention used by VisualStudio: \<control name>\_\<event name>. Inside the MessageActions handler there is a single switch statement, where each case expression is the equivalent of the original application's On\_\<message> items.

However, unlike the typical event handler generated by VisualStudio, the MessageActions event handler has only one parameter, which is passed by reference and it's a structure called *SalMessage*. This construct is similar to .NET's declaration of the *WndProc* message handler for Windows messages. This solution was adopted to increase the speed of dispatching messages and to reduce peak memory consumption. Structures in .NET are allocated on the stack and collected immediately, and when they are passed by reference they are not copied. It's like passing an integer.

Since all PPJ controls are directly derived from standard .NET controls, all regular events are available, are unmodified, and can be used. There is no duplication and there is no confusion. PPJ controls add only one event: MessageActions. Additionally, even where there seem to be similarities, like SAM\_Click and the Click event, one quickly finds out that the two are different and using the Click event when the code expects the behavior of SAM\_Click may lead to subtle errors and malfunctions. Many other SAM messages don't have an equivalent .NET event.

## Message handling

When a message is being handled in the *MessageActions* handler, the code should set the *message.Handled* flag to true. To increase execution speed, the PPJ Framework will not dispatch messages that are not handled. **If a message is not handled, it's dispatched only once.**

When handling a message, SAL code can return a value, or not return at all. If the return statement is not present in SAL, the CTD runtime interprets it to mean that the message can be dispatched to Windows default *WndProc*. Ported code has all the return statements translated into assignments to *message.Return*. When this assignment is missing, the PPJ Framework relays the message to the default *WndProc*. Otherwise, the value stored in *message.Return* becomes the value returned to the sender of the message. It's the same as assigning the *msg.Result* value when overriding the *WndProc* method.

All system's SAM messages are pumped directly to the *MessageActions* handlers and the execution is extremely fast.

## Sending and Posting messages

*Sal.SendMsg*() and *Sal.PostMsg*() use Windows *SendMessage* and *PostMessage* and can be used also to send non SAM messages.

## Windows messages

All Windows messages that are normally dispatched to the regular *WndProc*, are also relayed to the control's new *MessageActions* event and can be handled by the new .NET application.

## SalSendClassMessage

Usually .NET control's events are multicast. If several instances of an event handler are attached to an event, they are all invoked. The *MessageActions* event is different and is treated like a unicast event. When there are several *MessageActions* handler, only the last attached handler is invoked. This is consistent with SQLWindows/Team Developer behavior where message handling is overridden in derived classes.

The message can be passed up to the previous handler by calling *Sal.SendClassMessage* and ~~*Sal.SendClassMessageNamed*~~.

## Adding new MessageActions / WindowActions

To add a new *MessageActions* it's enough to double click on the PPJ control in design mode. Visual Studio will create the event handler, or jump to the existing event handler. If the handler is new, you need to add the switch statement like this:

```
switch (message.Code)
{
}
```

&#x20;To handle a new message, simply add the case block:

```
switch (message.Code)
        {
         case Sys.SAM_Click:
                 message.Handled = true;
                 ...
                 break;
        }
```

Starting from version 3.5 of the PPJ Framework the event *MessageActions* has been deprecated and replaced by the *WindowActions* event:

```
switch (e.ActionType)
{
 case Sys.SAM_Click:
         e.Handled = true;
         ...
         break;
}
```

{% hint style="success" %}
It's important to remember to add message.Handled = true otherwise the message will be dispatched only once because the PPJ Framework keeps track of the messages that have not been handled and avoids dispatching them a second time.
{% endhint %}
