Browse Source

+ Added message methods

michael 26 years ago
parent
commit
333d20bace
2 changed files with 163 additions and 5 deletions
  1. 156 4
      docs/ref.tex
  2. 7 1
      docs/syntax/typeclas.syn

+ 156 - 4
docs/ref.tex

@@ -800,10 +800,10 @@ error if S is an ansistring:
 \begin{verbatim}
 \begin{verbatim}
   Len:=S[0];
   Len:=S[0];
 \end{verbatim}
 \end{verbatim}
-Instead, you must use the \seefl{Length} function to get the length of a
+Instead, you must use the \seef{Length} function to get the length of a
 string.
 string.
 
 
-To set the length of an ansistring, you can use the \seepl{SetLength}
+To set the length of an ansistring, you can use the \seep{SetLength}
 function.
 function.
 Constant ansistrings have a reference count of -1 and are treated specially.
 Constant ansistrings have a reference count of -1 and are treated specially.
 
 
@@ -1723,7 +1723,8 @@ an object. To get the size of the class instance data, use the
 \var{TObject.InstanceSize} method.
 \var{TObject.InstanceSize} method.
 \end{itemize}
 \end{itemize}
 \section{Methods}
 \section{Methods}
-Method invocation for classes is no different than for objects. The
+\seubsection{invocation}
+Method invocaticn for classes is no different than for objects. The
 following is a valid method invocation:
 following is a valid method invocation:
 \begin{verbatim}
 \begin{verbatim}
 Var  AnObject : TAnObject;
 Var  AnObject : TAnObject;
@@ -1731,6 +1732,138 @@ begin
   AnObject := TAnObject.Create;
   AnObject := TAnObject.Create;
   ANobject.AMethod;
   ANobject.AMethod;
 \end{verbatim}
 \end{verbatim}
+\subsection{Virtual methods}
+Classes have virtual methods, just as objects do. There is however a
+difference between the two. For objects, it is sufficient to redeclare the
+same method in a descendent object with the keyword \var{virtual} to
+override it. For classes, the situation is different: you {\em must}
+override virtual methods with the \var{override} keyword. Failing to do so,
+will start a {\em new} batch of virtual methods, hiding the previous
+one.  The \var{Inherited} keyword will not jup to the inhherited method, if
+virtual was used. 
+
+The following code is {\em wrong}:
+\begin{listing}
+Type ObjParent = Class
+        Procedure MyProc; virtual;
+     end;
+     ObjChild  = Class(ObjPArent)
+       Procedure MyProc; virtual;
+     end;
+\end{listing}     
+The compiler will produce a warning:
+\begin{verbatim}
+Warning: An inherited method is hidden by OBJCHILD.MYPROC
+\end{verbatim}
+The compiler will compile it, but using \var{Inherited} can
+produce strange effects.
+
+The correct declaration is as follows:
+\begin{listing}
+Type ObjParent = Class
+        Procedure MyProc; virtual;
+     end;
+     ObjChild  = Class(ObjPArent)
+       Procedure MyProc; override;
+     end;
+\end{listing}
+This will compile and run without warnings or errors.
+
+\subsection{Message methods}
+New in classes are \var{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 \var{GUI} toolkits, such as \var{Win32} or
+\var{GTK}. In difference with Delphi, \fpc also accepts strings as message
+identifiers.
+
+Message methods that are declared with an integer constant can take only one
+var argument (typed or not):
+\begin{listing}
+ Procedure TMyObject.MyHandler(Var Msg); Message 1;
+\end{listing}
+The method implementation of a message function is no different from an
+ordinary method. It is also possible to call a message method directly,
+but you should not do this. Instead use the \var{TObject.Dispatch} method.
+
+The \var{TOBject.Dispatch} method can be used to call a \var{message}
+handler. It is  declared in the system unit will accept a var parameter 
+which must have at the first position a cardinal with the message ID that
+should be called. For example:
+\begin{listing}
+Type 
+  TMsg = Record
+    MSGID : Cardinal
+    Data : Pointer;
+Var
+  Msg : TMSg;
+
+MyObject.Dispatch (Msg);
+\end{listing}
+In this example, the \var{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 \var{MSGID} has been
+declared. If such a method is found, it is called, and passed the 
+\var{Msg} parameter.
+
+If no such method is found, \var{DefaultHandler} is called.
+\var{DefaultHandler} is a virtual method of \var{TObject} that doesn't do 
+anything, but which can be overridden to provide any processing you might
+need. \var{DefaultHandler} is declared as follows:
+\begin{listing}
+   procedure defaulthandler(var message);virtual;
+\end{listing}
+
+In addition to the message method with a \var{Integer} identifier,
+\fpc also supports a messae method with a string identifier:
+\begin{listing}
+ Procedure TMyObject.MyStrHandler(Var Msg); Message 'OnClick';
+\end{listing}
+
+The working of the string message handler is the same as the ordinary
+integer message handler:
+
+The \var{TOBject.DispatchStr} method can be used to call a \var{message}
+handler. It is declared in the system unit and will accept one parameter
+which must have at the first position a cardinal with the message ID that
+should be called. For example:
+\begin{listing}
+Type 
+  TMsg = Record
+    MsgStr : String[10]; // Arbitrary length up to 255 characters.
+    Data : Pointer;
+Var
+  Msg : TMSg;
+
+MyObject.DispatchStr (Msg);
+\end{listing}
+In this example, the \var{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 \var{MsgStr} has been
+declared. If such a method is found, it is called, and passed the 
+\var{Msg} parameter.
+
+If no such method is found, \var{DefaultHandlerStr} is called.
+\var{DefaultHandlerStr} is a virtual method of \var{TObject} that doesn't do 
+anything, but which can be overridden to provide any processing you might
+need. \var{DefaultHandlerStr} is declared as follows:
+\begin{listing}
+   procedure DefaultHandlerStr(var message);virtual;
+\end{listing}
+
+In addition to this mechanism, a string message method accepts a \var{self}
+parameter:
+\begin{listing}
+  TMyObject.StrMsgHandler(Data : Pointer; Self : TMyObject);Message 'OnClick';
+\end{listing}
+When encountering such a method, the compiler will generate code that loads
+the \var{Self} parameter into the object instance pointer. The result of
+this is that it is possible to pass \var{Self} as a parameter to such a
+method. 
+
+{\em remark:} The type of the \var{Self} parameter must be of the same class
+as the class you define the method for.
+
 \section{Properties}
 \section{Properties}
 Classes can contain properties as part of their fields list. A property
 Classes can contain properties as part of their fields list. A property
 acts like a normal field, i.e. you can get or set it's value, but
 acts like a normal field, i.e. you can get or set it's value, but
@@ -3502,7 +3635,7 @@ const
   errorcode : word = 0;
   errorcode : word = 0;
  { max level in dumping on error }
  { max level in dumping on error }
   max_frame_dump : word = 20;
   max_frame_dump : word = 20;
-\end{verbatim}
+\end{listing}
 \emph{ Remark: } Processor specific global constants are named Testxxxx
 \emph{ Remark: } Processor specific global constants are named Testxxxx
 where xxxx represents the processor number (such as Test8086, Test68000),
 where xxxx represents the processor number (such as Test8086, Test68000),
 and are used to determine on what generation of processor the program
 and are used to determine on what generation of processor the program
@@ -4872,6 +5005,25 @@ None.
 \end{function}
 \end{function}
 \latex{\inputlisting{refex/ex79.pp}}
 \latex{\inputlisting{refex/ex79.pp}}
 \html{\input{refex/ex79.tex}}
 \html{\input{refex/ex79.tex}}
+
+\begin{procedure}{SetLength}
+\Declaration
+Procedure SetLength(var S : String; Len : Longint);
+\Description
+\var{SetLength} sets the lentgth of the string \var{S} to \var{Len}. \var{S}
+can be an ansistring or a short string. 
+For \var{ShortStrings}, \var{Len} can maximally be 255. For \var{AnsiStrings}
+it can have any value. For \var{AnsiString} strings, \var{SetLength} {\em
+must} be used to set the length of the string.
+\Errors
+None.
+\SeeAlso
+\seef{Length}
+\end{procedure}
+
+\latex{\inputlisting{refex/ex85.pp}}
+\html{\input{refex/ex85.tex}}
+
 \begin{procedure}{SetTextBuf}
 \begin{procedure}{SetTextBuf}
 \Declaration
 \Declaration
 Procedure SetTextBuf (Var f : Text; Var Buf[; Size : Word]);
 Procedure SetTextBuf (Var f : Text; Var Buf[; Size : Word]);

+ 7 - 1
docs/syntax/typeclas.syn

@@ -43,7 +43,13 @@
 \)
 \)
 \lit*;
 \lit*;
 \[
 \[
-\lit*{virtual} \lit*;
+  \( \lit*{virtual}  \\
+     \lit*{override} \\
+     \lit*{message} 
+      \( \synt{integer\ constant} \\
+         \synt{string\ constant} \)
+  \) 
+\lit*;
 \]
 \]
 \[ \synt{call\ modifiers} \lit*; \]
 \[ \synt{call\ modifiers} \lit*; \]
 \[
 \[