Delphi

Using Run-Time Type Information in Delphi

Runtime Type Information in Delphi (RTTI)

There are a number of RTTI-related technologies available in Delphi. The fact that every class is derived from TObject means that there are some methods generally available to each class, such as className, which returns a string with the name of the class of an object. The Delphi compiler generates RTTI for published properties (but not public properties).

The ClassInfo function returns a pointer to the RTTI information for a class.

RTTI provides an easy way to determine if an object's type is that of a particular class or one of its descendants. The is and as operators provide access to the RTTI and can be used to provide generic routines ie.

procedure TForm1.SpeedButton1Click(Sender: TObject);
var
  anEdit : TCustomEdit;
begin
  if ActiveControl is TCustomEdit then
  begin
    anEdit := ActiveControl as TCustomEdit;
    anEdit.SelStart := 0;
    anEdit.SelLength := length(anEdit.Text);
    anEdit.CopyToClipboard;
  end;
end;

Note: the text in the edit control must first be selected before the CopyToClipboard will work. Normally, the user selects the text using either the mouse or the keyboard but here the code selects all the text regardless of what the user selected.

procedure TForm1.SpeedButton2Click(Sender: TObject);
begin
  Edit2.SelStart := 0;
  Edit2.SelLength := length(Edit2.Text);
  Edit2.PasteFromClipboard;
end;

The above code will copy the text in any control descended from TEdit and then paste it into the named edit control. It demonstrates the use of both the is and as operators. Add both a TEdit and a TMemo to a form and place the above code in the OnClick event of two speed buttons captioned Cut and Paste respectively and play around.

Use of RTTI by Delphi

The Delphi 3 Help File states:

The Delphi Visual Component Library uses the run-time type information generated for published sections to access the values of a component's properties when saving a loading form files. Furthermore, the Delphi IDE uses a component's run-time type information to determine the list of properties to show in the Object Inspector.

Certain low-level VCL procedures and functions require run-time type information pointers as parameters. The actual format of the run-time type information is internal to the compiler and may change between releases.

In Delphi 3, the generation of RTTI is controlled by the $M (or $TYPINFO) compile directive. The Delphi 3 help file states that any component derived from TPersistent will have RTTI information. However, you can generate RTTI for other classes by using the directive prior to its definition.

Using RTTI

RTTI is poorly described in Delphi. The only available information is the interface described in TYPINFO.PAS. Fortunately, others have documented the mechanics of calling the RTTI methods notably Ray Lischner in his book Secrets of Delphi 2. For further information you could search for RTTI and Delphi in Google Groups for this.

For example, if you wanted to build a listbox containing the names of say the TPenStyle you could do the following:
uses typinfo; var
  a : integer;
  begin
    for a := Ord(Low(TPenStyle)) to Ord(High(TPenStyle)) do
    {$IFDEF WIN32}
      ListBox1.Items.Add(GetEnumName(TypeInfo(TPenStyle),a));
    {$ELSE}
      ListBox1.Items.Add(GetEnumName(TypeInfo(TPenStyle),a)^);
    {$ENDIF}
  end;

By the way, the '^' must be added to the source if you use Delphi 1 compiler but is not necessary in Delphi 3! I am unsure about Delphi 2 - try it and let me know. Also, the TypeInfo function is not documented in the Help files (either Delphi 1 or Delphi 3) but returns a pointer. It is used occasionally within the VCL.

This technique has the advantage over the old hard-code the values as it is quicker and does not need to be changed if the new pen styles are added. Other procedures are available to get and set the property values.

Another neat trick using RTTI

This is quite useful to perform the same action (say setting the colour) on all components within a parent control. Have a look at Using RTTI with properties for a more detailed notes on how to use RTTI to set the colour of a control.

Saving Run-Time Form Property Values

The ability to save and then restore the properties of components on a form is the sign of a user-friendly application. When this sort of application starts, the visual controls contain the same information when the application was closed. There are numerous techniques available to achieve this usually involving either .INI files or the Registry.

If you have a masochistic streak, code can be written in both the FormCreate and FormClose events to save each individual field or special components written which subclass the existing components and save the required values.

Saving Run-Time Property Values - The Smart Approach

The next step in this process may now be obvious - use RTTI. Thankfully the JEDI Project has a excellent implementation of this - a series of components TJvStorage, TJvAppIniFileStorage, and others.

Exploring the Forms, Components, and Properties

RTTI allows allows access to all published properties on a form. My next example allows the investigation of these for the project. Have a look at the form titled Property Explorer Version 2 which demonstrates each form within the project and then the components and properties within. Given that RTTI contains all the properties and methods, it would seem possible to write an expert to generate the RTF (Rich Text Format) source for a component help file but this is beyond the scope of this presentation.

References

Last Revised: 

Copyright 1998-2007

gra...@pcug.org.au