Chapter 7: Porting Delphi components

by Michael Van Canneyt and Mattias Gärtner When you need to port a Delphi application to Lazarus, you will often encounter the need to port not only Delphi VCL components but a variety of third-party Delphi components, all of which have to be converted to work under Lazarus in a cross-platform way. For most non-visual components, the conversion work required is not very complicated. However, when you port visual components from a Windows-only development environment (Delphi) to the new platforms accessible through Lazarus you will have to undertake considerably more work, particularly for visual components that make direct calls to the Windows API (as most Delphi visual components do). All those calls to the Windows API in the code you encounter will have to be replaced with platform-independent equivalents. To do that, you have to know how Lazarus components are built.

7.1 The Architecture of Lazarus Components

The LCL offers many components, with very different capabilities. You can use these to develop applications quickly and easily. In addition to the components shipped with Lazarus, there are many third-party components available which extend the functionalities of the basic Lazarus components. This chapter explains the basic building blocks of the LCL, and gives an overview of the whole process of developing custom components. This knowledge should make it possible for you to understand how to port third-party components to Lazarus successfully. The LCL is based on two sets of hierarchical class trees, which are tightly coupled to each other. One of these sets of classes is the platform-independent part – the components on the component palette (such as TButton) belong to this set, and this set is Delphi compatible. The second set of classes is the so-called widget-set or, more precisely, the Lazarus interface to the native widget-set. A widget-set is a native library, for example GTK on Linux, or the WinAPI on Windows. The interface between the platform-independent LCL (TButton, for example) to the GTK native button (called gtk_button) is called the LCL interface. Each LCL interface is named after the underlying widget-set to which it binds. For this reason, the concepts of the widget-set and the LCL interface are often used as synonyms. Not all LCL components have a counterpart in the widget-set, and often custom components are simply build on top of the platform-independent part of the LCL. Consequently the platform-independent part will be described first. The relation between the various classes is depicted in Figure 7.1. The various parts of a Lazarus application are shown. The arrows indicate for each part with which other parts it communicates. The as can be seen, only the LCL Classes communicate with the widget-set classes. This means that the widget set classes can be replaced with another widget set, and the application will function without any code changes. 494
Lazarus - the complete guide

7.1.1 The LCL's platform-independent layer

7.1.1 The LCL's platform-independent layer

All LCL components descend from the TLCLComponent class, which descends from the TComponent class. TComponent is defined in the FCL (the Free Pascal Component Library) and it provides two important features. Firstly, TComponent inherits from TPersistent the ability to define published properties which lets the compiler generate code to allow the properties to be read and set at runtime in a generic way. This is what allows the Object Inspector to display and manipulate a component's published properties. The second important feature provided by TComponent is its ability to stream its published properties to a stream, of which the .lfm file is an example. This works because all components have a Name property and can be nested; and this enables you to drop, say, a TButton on a TForm instance in the Form Designer. TComponent's streaming capabilities are very powerful, allowing both inheritance and nesting – something which is supported visually in the Lazarus IDE. This double functionality built in to TComponent is also the reason why most third-party components are TComponent descendants. You can find an example showing how easy it is to save a component with all its children to a stream (and how they can be read again from this stream) in the Lazarus source tree in the directory examples/componentstreaming.

Application Code

LCL Classes

Widgetset Classes Widgetset Library

FCL / RTL

Operating System/GUI System

Figure 7.1: The relation between the various classes

Lazarus - the complete guide

495

Master your semester with Scribd & The New York Times

Special offer for students: Only $4.99/month.

Master your semester with Scribd & The New York Times

Cancel anytime.