New in classes are message methods. Pointers to message methods are stored in a special table, together with the integer or string cnstant 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 di erence with Delphi, Free Pascal also accepts strings as message identi ers.
Message methods that are declared with an integer constant can take only one var argument (typed or not):
Procedure TMyObject.MyHandler(Var Msg); Message 1;
|
The method implementation of a message function is no di erent 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.
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 rst 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 it's ancestors (starting at the object, and searching up the 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 identi er, Free Pascal also supports a message method with a string identi er:
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 rst position a 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 it's ancestors (starting at the object, and searching up the 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:
TMyObject.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 de ned in.