6.5.7 Message methods

New in classes are message methods. Pointers to message methods are stored in a special table, together with the integer or string constant that they were declared with. They are primarily intended to ease programming of callback functions in several GUI toolkits, such as Win32 or GTK. In difference with Delphi, Free Pascal also accepts strings as message identifiers. Message methods are always virtual.

As can be seen in the class declaration diagram, message methods are declared with a Message keyword, followed by an integer constant expression.

Additionally, they can take only one var argument (typed or not):

 Procedure TMyObject.MyHandler(Var Msg); Message 1;

The method implementation of a message function is not different from an ordinary method. It is also possible to call a message method directly, but this should not be done. Instead, the TObject.Dispatch method should be used. Message methods are automatically virtual, i.e. they can be overridden in descendent classes.

The TObject.Dispatch method can be used to call a message handler. It is declared in the system unit and will accept a var parameter which must have at the first position a cardinal with the message ID that should be called. For example:

Type  
  TMsg = Record  
    MSGID : Cardinal;  
    Data : Pointer;  
Var  
  Msg : TMSg;  
 
MyObject.Dispatch (Msg);

In this example, the Dispatch method will look at the object and all its ancestors (starting at the object, and searching up the inheritance class tree), to see if a message method with message MSGID has been declared. If such a method is found, it is called, and passed the Msg parameter.

If no such method is found, DefaultHandler is called. DefaultHandler is a virtual method of TObject that doesn’t do anything, but which can be overridden to provide any processing that might be needed. DefaultHandler is declared as follows:

   procedure DefaultHandler(var message);virtual;

In addition to the message method with a Integer identifier, Free Pascal also supports a message method with a string identifier:

 Procedure TMyObject.MyStrHandler(Var Msg); Message ’OnClick’;

The working of the string message handler is the same as the ordinary integer message handler:

The TObject.DispatchStr method can be used to call a message handler. It is declared in the system unit and will accept one parameter which must have at the first position a short string with the message ID that should be called. For example:

Type  
  TMsg = Record  
    MsgStr : String[10]; // Arbitrary length up to 255 characters.  
    Data : Pointer;  
Var  
  Msg : TMSg;  
 
MyObject.DispatchStr (Msg);

In this example, the DispatchStr method will look at the object and all its ancestors (starting at the object, and searching up the inheritance class tree), to see if a message method with message MsgStr has been declared. If such a method is found, it is called, and passed the Msg parameter.

If no such method is found, DefaultHandlerStr is called. DefaultHandlerStr is a virtual method of TObject that doesn’t do anything, but which can be overridden to provide any processing that might be needed. DefaultHandlerStr is declared as follows:

   procedure DefaultHandlerStr(var message);virtual;

In addition to this mechanism, a string message method accepts a self parameter:

Procedure StrMsgHandler(Data: Pointer;  
                        Self: TMyObject); Message ’OnClick’;

When encountering such a method, the compiler will generate code that loads the Self parameter into the object instance pointer. The result of this is that it is possible to pass Self as a parameter to such a method.

Remark: The type of the Self parameter must be of the same class as the class the method is defined in.