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)
{
}

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

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.

Last updated