Sign in Join
Wiki copytemporary

Lazarus For Delphi Users: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11This writeup is for people who are interested in Lazarus and already know Delphi. It describes the differences between the two.
22
33## Delphi -\> Lazarus
44
55Lazarus is a Rapid Application Development (RAD) tool like Delphi. That means it comes with a visual component library and an Integrated Development Environment (IDE). The Lazarus component library (LCL) is very similar to Delphi's Visual Component Library (VCL). Most Lazarus units, classes and properties have the same name and functionality as their equivalents in Delphi. This makes porting Delphi applications to Lazarus relatively easy. Even though Lazarus is in many respects an open source Delphi clone, the compatibility is not 100%.
66
77### The biggest differences between Lazarus and Delphi
88
99- Lazarus is completely open source
1010- Lazarus is written in a platform-independent way
1111- Lazarus uses the [[Free Pascal]] compiler (FPC)
1212
1313FPC runs on more than 15 platforms (see [[Platform list]]. But not all FPC packages and libraries have been ported to all 15 platforms, so Lazarus currently runs on:
1414
1515- Linux (i386, x86_64)
1616- FreeBSD (i386, x86_64)
1717- macOS (PowerPC, i386, x86_64, ARM64)
1818- Windows (i386, x86_64)
1919
2020> **Note:** Lazarus is not complete and nor, for that matter, is this text. We are always searching for new developers, packagers, porters, documentation writers...
2121
2222### The first thing to do when converting a Delphi project to Lazarus
2323
2424Having opened Lazarus, you should go to to **Tools** and then **Convert Delphi Project to Lazarus Project** (Since Lazarus 1.2.6 the menu structure is **Tools** -\> **Delphi Conversion** -\> **Convert Delphi Project to Lazarus Project**). This won't do everything for you, but nonetheless will take you a good deal of the way. Note that the Lazarus IDE's conversion tools are generally one-way conversions. If you need to retain Delphi compatibility (so you can compile your project with both Delphi and Lazarus) consider converting your files with the [XDev Toolkit](http://wiki.lazarus.freepascal.org/XDev_Toolkit) instead.
2525
2626### Unicode support
2727
2828Versions of Delphi up to Delphi 2007 didn't support Unicode, but used Windows ANSI encoding. Delphi supports Unicode by using UTF-16 encoded strings from the 2009 version.
2929
3030Lazarus on the other hand started its Unicode support earlier and uses UTF-8 encoded strings. For more information see [[LCL Unicode Support]].
3131
3232## Delphi IDE -\> Lazarus IDE
3333
3434### Projects
3535
3636The main file for a Delphi application is its .dpr file. A Delphi .dpr file is both the program main source, and also the file where the Delphi IDE stores information about relevant compiler switches and unit locations.\
3737A Lazarus application has a corresponding .lpr file, which is also the principal **Pascal source** file for the project. However, the main file of a Lazarus project is the .lpi file (Lazarus Project Information), which is created separately together with the .lpr file. All project-specific information (such as compiler switches used, paths to units used etc.) is stored in the .lpi file. So, the important file is the .lpi file. On most platforms, double-clicking on an .lpi file in the system's file explorer will start the Lazarus IDE with that project open.
3838
3939For example:
4040
4141Delphi stores the paths of the project's units in the .dpr file. For instance:
4242
4343` unit1 in 'path/Unit1.pas';`
4444
4545These 'in' paths are Delphi-specific and are not read by the Lazarus IDE. Don't use them. Instead, in the Project Options dialog (**Project**-\>**Project Options...**) use the **Paths** page under **Compiler Options** to set unit paths where they differ from the project directory path. Note that most unit paths you will need are set automatically by the IDE when any package dependency is added. For instance, all standard Lazarus LCL projects have the LCL added as a dependency by default, and so any new Lazarus LCL project (**Project**-\>**New Project**-\>**Application**) knows all paths to all LCL compiled units without further work on your part.
4646
4747Delphi stores compiler options in the .dpr file. For instance {\$APPTYPE CONSOLE}. These are ignored by the Lazarus IDE. Don't use them. Use the Compiler Options page of the Project Options dialog instead.
4848
4949### No "empty" IDE with Lazarus
5050
5151One important rule: There is *always* a project. The only way to "close" a project is to exit Lazarus, or open another project. This is because a Lazarus project is also a "session". So session information (e. g. the current editor settings) is also stored in the .lpi file and the Lazarus editor is restored to its last saved state when the project is later reopened. For example: You are debugging an application, and set a lot of breakpoints and bookmarks. You can save the project at any time, close Lazarus or open another project. When you reopen the project (even on another computer) all your breakpoints, bookmarks, open files, cursor positions, jump histories, etc. are restored.
5252
5353### Source Editor
5454
5555Nearly all keys and short cuts can be defined in Tools -\> Options -\> Editor -\> Key Mappings
5656
5757The Lazarus IDE has a lot of tools for sources. Many of them look and work very similar to Delphi. But there is one important difference: Lazarus does not use the compiler to get code information. It parses the sources directly. This has a lot of important advantages:
5858
5959The source editor works with "comments". For Delphi the comments in the source are just space between code. No code feature works there and when new code is auto inserted, your comments will travel. Under Lazarus you can do a find declaration even on code in comments. Although this is not completely reliable, it often works. And when new code is inserted, the IDE uses some heuristics to keep comment and code together. For example: It will not split the line "c: char; // comment".
6060
6161Delphi's "Code Completion" (Ctrl+Space) is called "Identifier Completion" under Lazarus. The Lazarus term "Code Completion" is a feature, combining "Automatic Class Completion" (same as under Delphi), "Local Variable Completion" and "Event Assignment Completion". All of them are invoked by Ctrl+Shift+C and the IDE determines by the cursor position, what is meant.
6262
6363#### Example for Local Variable Completion
6464
6565Assume you just created a new method and wrote the statement "i:=3;"
6666
6767``` pascal
6868procedure TForm1.DoSomething;
6969begin
7070 i := 3;
7171end;
7272```
7373
74-Position the cursor over the identifier "i" and press <span class="kbd">Ctrl</span>+<span class="kbd">Shift</span>+<span class="kbd">C</span> to get:
74+Position the cursor over the identifier "i" and press `Ctrl`+`Shift`+`C` to get:
7575
7676``` pascal
7777procedure TForm1.DoSomething;
7878var i: Integer;
7979begin
8080 i := 3;
8181end;
8282```
8383
8484#### Example for Event Assignment Completion
8585
8686A nice feature of the object inspector is to auto create methods. You can get the source editor to create the events too.\
8787For example:
8888
8989``` pascal
9090Button1.OnClick:=
9191```
9292
93-Position the cursor behind the assign operator ":=" and press <span class="kbd">Ctrl</span>+<span class="kbd">Shift</span>+<span class="kbd">C</span> to get:
93+Position the cursor behind the assign operator ":=" and press `Ctrl`+`Shift`+`C` to get:
9494
9595``` pascal
9696procedure TForm1.FormCreate(Sender: TObject);
9797begin
9898 Button1.OnClick:=@Button1Click;
9999end;
100100
101101procedure TForm1.Button1Click(Sender: TObject);
102102begin
103103
104104end;
105105```
106106
107107#### Example for Procedure Call Completion
108108
109109Assume you just wrote the statement "DoSomething(Width);"
110110
111111``` pascal
112112procedure SomeProcedure;
113113var
114114 Width: integer;
115115begin
116116 Width:=3;
117117 DoSomething(Width);
118118end;
119119```
120120
121-Position the cursor over the identifier "DoSomething" and press <span class="kbd">Ctrl</span>+<span class="kbd">Shift</span>+<span class="kbd">C</span> to get:
121+Position the cursor over the identifier "DoSomething" and press `Ctrl`+`Shift`+`C` to get:
122122
123123``` pascal
124124procedure DoSomething(aWidth: LongInt);
125125begin
126126
127127end;
128128
129129procedure SomeProcedure;
130130var
131131 Width: integer;
132132begin
133133 Width:=3;
134134 DoSomething(Width);
135135end;
136136```
137137
138138#### "Word Completion" Ctrl+W
139139
140140It works similar to the "Identifier Completion", but it does not work on pascal identifiers, but on all words. It lets you choose of all words in all open files beginning with the same letters.
141141
142142#### Supports Include files
143143
144144Delphi didn't support them, and so you probably haven't created many include files yet. But include files have a big advantage: They make it possible writing platform (in)dependent code without messing your code with IFDEFs. For example: Method jumping, Class Completion, find declaration, .. all work with include files.
145145
146146There are many options for the code features.
147147
148148### Designer
149149
150150\- Guidelines
151151
152152#### Object Inspector
153153
154154In the Delphi and Lazarus IDE's the Object Inspector is used to edit component properties and assign events etc. The following are a few minor differences to note in use :
155155
1561561. Starting in Delphi 5 there is an Object Treeview which can be used to navigate and select objects according to hierarchy in addition to the traditional drop down list in the Object Inspector. In Lazarus this is part of the Object Inspector and is used in place of the default drop-down, you can select to use/not use it from the right click menu with "Show Component Tree"
1571572. In Delphi double clicking on a blank event will auto create one and open the Source Editor to that position, in Lazarus there is a button to the right of the selected drop-down which performs this action instead.
1581583. In Delphi you must manually delete the name of an event in the edit to remove the attatchement, in Lazarus you can drop down and select "(None)".
1591594. Similarly to Events, double clicking regular properties such as boolean will not change the value, you must select it from a drop down. And to open those with an assigned editor form, you must click the '...' button to the right of the edit/drop-down
160160
161161#### Packages
162162
163163Can Lazarus install and use Delphi Packages?
164164
165165
166166No, because they require Delphi compiler magic.
167167
168168Do we need ones specially made for lazarus?
169169
170170
171171Yes.
172172
173173Create a new package, save it in the package source directory (normally same directory of the .dpk file), add the LCL as required package and finally add the .pas files. You can install it, or use it in your projects now. There are some [[packages|differences between Lazarus and Delphi packages]]
174174
175175## VCL -\> LCL
176176
177177While the VCL and the LCL both serve much of the same purpose - of an Object Oriented Component Hierarchy especially geared toward rapid application development, they are not identical. For instance while the VCL provides many non-visual components, the LCL tries to only provide visual, while most non-visual components (such as db access) are provided by the FCL, included with [[Free Pascal]] .
178178
179179Additionally many controls may not exist in the LCL that are in the VCL, or vice versa, or even when controls do exist in both, they are not clones, and changes must be made in applications, components and controls if porting.
180180
181181The following is an attempt to provide fairly complete descriptions of major differences or incompatiblities between the two for the Delphi user. It covers differences primarily with the VCL of D4 especially, though at times D5, D6, or D7 as well; and with the current LCL, as is in CVS. As such it may not always be accurate to the version of Delphi you are used to, or completely match the current LCL you have. If you see inacuracies between the following and the LCL as in CVS, or your Delphi feel free to append and modify so as to keep this as comprehensive as possible for all people.
182182
183183### TControl.Font/TControl.ParentFont
184184
185185In the VCL it is quite common and normal to use a specific font name and font properties such as bold and italics for controls, and expect this value to always be followed. Further is provided the TControl.ParentFont property which ensures that a control will always follow its parent's font. Again the implicit assumption being that these values will always be followed, even regardless of Windows Apearance Settings.
186186
187187This is not always true in the LCL, nor can it be. The LCL being cross-platform/cross-interface in nature prefers to take a balanced aproach, and instead will always try to use native Desktop/Toolkit Apearance or Theme settings on any widgets. For example if using a GTK interface, and the gtk theme supplies a specific font for buttons, then LCL buttons will always try to use this font.
188188
189189This means that most LCL controls do not have the same level of design control that is often expected in the VCL, rather only those custom controls which are Canvas drawn instead of interface allocated can consistantly be modified in this manner regardless of the Interface used.
190190
191191### Control Dragging/Docking
192192
193193In the VCL most (Win)Controls implement methods and [[callback]] functions for handling dragging and docking of controls, eg. dragging a control from one panel, and docking it onto another panel at run time.
194194
195195This functionality is currently unimplemented/unfinished in the LCL, though it is currently in the initial stages of planning, and should eventually support some level of compatibility for this type of behavior, if not in the exact same manner.
196196
197197This currently means that no Control will inherit/use the following TControl functions, procedures, properties, or events -
198198
199199``` pascal
200200Protected
201201 function GetDockEdge(MousePos: TPoint): TAlign;
202202 function GetDragImages: TDragImageList;
203203 function GetFloating: Boolean;
204204 function GetFloatingDockSiteClass: TWinControlClass;
205205 procedure DoEndDrag(Target:TObject); X, Y: Integer);
206206 procedure DockTrackNoTarget(Source: TDragDockObject; X, Y: Integer);
207207 procedure DoEndDock(Target: TObject; X, Y: Integer);
208208 procedure DoDock(NewDockSite: TWinControl; var ARect: TRect);
209209 procedure DoStartDock(var DragObject: TDragObject);
210210 procedure DragCanceled;
211211 procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState;
212212 var Accept: Boolean);
213213 procedure DoEndDrag(Target: TObject; X, Y: Integer);
214214 procedure DoStartDrag(var DragObject: TDragObject);
215215 procedure DrawDragDockImage(DragDockObject: TDragDockObject);
216216 procedure EraseDragDockImage(DragDockObject: TDragDockObject);
217217 procedure PositionDockRect(DragDockObject: TDragDockObject);
218218 procedure SetDragMode(Value: TDragMode);
219219 property DragKind: TDragKind;
220220 property DragCursor: TCursor;
221221 property DragMode: TDragMode;
222222 property OnDragDrop: TDragDropEvent;
223223 property OnDragOver: TDragOverEvent;
224224 property OnEndDock: TEndDragEvent;
225225 property OnEndDrag: TEndDragEvent;
226226 property OnStartDock: TStartDockEvent;
227227 property OnStartDrag: TStartDragEvent;
228228public
229229 function Dragging: Boolean;
230230 function ManualDock(NewDockSite: TWinControl; DropControl: TControl;
231231 ControlSide: TAlign): Boolean;
232232 function ManualFloat(ScreenPos: TRect): Boolean;
233233 function ReplaceDockedControl(Control: TControl; NewDockSite: TWinControl;
234234 DropControl: TControl; ControlSide: TAlign): Boolean;
235235 procedure BeginDrag(Immediate: Boolean; Threshold: Integer);
236236 procedure Dock(NewDockSite: TWinControl; ARect: TRect);
237237 procedure DragDrop(Source: TObject; X, Y: Integer);
238238 procedure EndDrag(Drop: Boolean);
239239 property DockOrientation: TDockOrientation;
240240 property Floating: Boolean;
241241 property FloatingDockSiteClass: TWinControlClass;
242242 property HostDockSite: TWinControl;
243243 property LRDockWidth: Integer;
244244 property TBDockHeight: Integer;
245245 property UndockHeight: Integer;
246246 property UndockWidth: Integer;
247247```
248248
249249that the following classes do not exist/are unusable -
250250
251251``` pascal
252252TDragImageList = class(TCustomImageList)
253253TDockZone = class
254254TDockTree = class(TInterfacedObject, IDockManager)
255255TDragObject = class(TObject)
256256TBaseDragControlObject = class(TDragObject)
257257TDragControlObject = class(TBaseDragControlObject)
258258TDragDockObject = class(TBaseDragControlObject)
259259```
260260
261261and that the following functions are also unusable/incompatible -
262262
263263``` pascal
264264function FindDragTarget(const Pos: TPoint;
265265 AllowDisabled: Boolean) : TControl;
266266procedure CancelDrag;
267267function IsDragObject(sender: TObject): Boolean;
268268```
269269
270270The start of docking manager is described here: [[Anchor Docking]]
271271
272272### TEdit/TCustomEdit
273273
274274The Edit controls, while functioning essentialy the same in the LCL as the VCL, do have some issues to be aware of in converting -
275275
2762761. Due to restrictions in the Interfaces, TEdit.PasswordChar does not work in all interfaces yet(though in time it may), instead TCustomEdit.EchoMode emPassword should be used in the event text needs to be hidden.
2772772. On Drag/Dock Events are not yet implemented. For more information please see earlier section on Control Dragging/Docking.
2782783. Font Properties are usually ignored for interface consistancy, for detailed explanation as too why please see TControl.Font/TControl.ParentFont
279279
280280### TDBImage
281281
282282Delphi and Lazarus both have a [[TDBImage]] control that shows images stored in a database field. In current stable versions (1.2.4), Lazarus stores information about the image type in the database field before the actual image data. See procedure *TDBImage.UpdateData* This means that Delphi and older Lazarus implementations are not compatible.
283283
284284Current stable Lazarus (1.2.0+) has implemented changes that allow Delphi compatible behaviour. Please see [[Lazarus 1.2.0 release notes|Lazarus_1.2.0_release_notes#TDBImage]] for details on how to activate this.
285285
286286Current Lazarus trunk falls back to Delphi-compatible behaviour on reading Delphi-formatted database fields into TDBImage.
287287
288288### (optional) TSplitter -\> TPairSplitter
289289
290290**Please Improve Me**
291291
292292There is now a [[TSplitter]] control in the LCL, so no need to convert it.
293293
294294Nevertheless, if you want, here it is explained:
295295
296296The following is loosely based on questions by Vincent Snijders on the mailing list, and responses by [Andrew Johnson](http://lazarus-ccr.sourceforge.net/index.php?wiki=AndrewJohnson):
297297
298298In the VCL, "Splitting" controls, that is a handle which can be dragged between two components to give one more or less space then the other, is accomplished by a TSplitter. This is often seen, for instance in the Delphi IDE between the docked Code Explorer and Source Viewer.
299299
300300The LCL provides its own Control called a TPairSplitter, which serves the same type of purpose, however it is not compatible, so "repairing" broken VCL code or Delphi DFM's will be necessary in the event of porting code, even though much is shared in common between the two.
301301
302302So what exactly are the differences?
303303
304304Well the biggest differences are a VCL TSplitter has no children, instead it is placed between two controls aligned properly, and allows resizing between them at runtime, regardless its own size. It must have two controls aligned on each side to do anything. A simple example would be form with a Left Aligned Panel, a left aligned Splitter, and a second client aligned panel. On run time you could then realign the size given each panel by dragging on the handle provided by this Splitter control.
305305
306306On the LCL hand however, a TPairSplitter is a special kind of control, with two panels, and it can only be usefull if the controls to split are on these panels, but it will still perform a split between those panel whether or not anything is on them. So following the prior example, you would have a form with a TPairSplitter aligned client, and a panel aligned client on its left side, and a panel aligned client on its right side.
307307
308308The other important difference is that in the VCl, since the TSplitter is its own TControl, then the position is kept relative to the other controls on resize, so for instance a client panel will grow while the other panels will not, thus the split position is relative to the alignment of the split controls,
309309
310310In the LCL since the side panels are separate then the TPairSplitter has a Position property which is absolute relative to top or left. so on resize the actual position does not change according to contents, so a callback must be set to ensure the ratio is kept on resize if this is important.
311311
312312For example if the Right side of a vertical split needs to have alClient like behaviour, you need to add a form resize callback which does something like :
313313
314314`PairSplitter.Position := PairSplitter.Width - PairSplitter.Position; `
315315
316316So how can I convert existing code using TSplitter to the TPairSplitter?
317317
318318If the splitter and controls are created within an actual function(like form oncreate), conversion shouldn't be too difficult, primarily reorganize the code to create the controls in order of new hierarchy and set the parents of the child controls to split to the left/top and right/bottom portions of the PairSplitter. An example of the changes being -
319319
320-<table>
321-<tbody>
322-<tr>
323-<td class="header"><p><strong>VCL</strong></p></td>
324-<td class="header"><p><strong>LCL</strong></p></td>
325-</tr>
326-<tr>
327-<td class="code"><div class="sourceCode" id="cb1"><pre class="sourceCode pascal"><code class="sourceCode pascal"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> </span>
328-<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a> BottomPanel: TPanel;</span>
329-<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> VerticalSplitter: TSplitter;</span>
330-<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a> LeftPanel: TPanel;</span>
331-<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a> HorizontalSplitter: TSplitter;</span>
332-<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a> MainPanel: TPanel;</span>
333-<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
334-<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="kw">begin</span></span>
335-<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a> BottomPanel:= TPanel.Create(<span class="kw">Self</span>);</span>
336-<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a> <span class="kw">with</span> (BottomPanel) <span class="kw">do</span></span>
337-<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a> <span class="kw">begin</span></span>
338-<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a> Parent:= <span class="kw">Self</span>;</span>
339-<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a> Height:= <span class="dv">75</span>;</span>
340-<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a> Align:= alBottom;</span>
341-<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span>;</span>
342-<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a></span>
343-<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a> VerticalSplitter:= TSplitter.Create(<span class="kw">Self</span>);</span>
344-<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a> <span class="kw">with</span> (VerticalSplitter) <span class="kw">do</span></span>
345-<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a> <span class="kw">begin</span></span>
346-<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a> Parent:= <span class="kw">Self</span>;</span>
347-<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a> Align:= alBottom;</span>
348-<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span>;</span>
349-<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a></span>
350-<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a> HorizontalSplitter:= TSplitter.Create(<span class="kw">Self</span>);</span>
351-<span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a> <span class="kw">with</span> (HorizontalSplitter) <span class="kw">do</span></span>
352-<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a> <span class="kw">begin</span></span>
353-<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a> Parent:= <span class="kw">Self</span>;</span>
354-<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a> align:= alLeft;</span>
355-<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span>;</span>
356-<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a></span>
357-<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a> LeftPanel:= TPanel.Create(<span class="kw">Self</span>);</span>
358-<span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a> <span class="kw">with</span> (LeftPanel) <span class="kw">do</span></span>
359-<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a> <span class="kw">begin</span></span>
360-<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a> Parent:= <span class="kw">Self</span>;</span>
361-<span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a> Width:= <span class="dv">125</span>;</span>
362-<span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a> Align:= alLeft;</span>
363-<span id="cb1-37"><a href="#cb1-37" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span>;</span>
364-<span id="cb1-38"><a href="#cb1-38" aria-hidden="true" tabindex="-1"></a></span>
365-<span id="cb1-39"><a href="#cb1-39" aria-hidden="true" tabindex="-1"></a> MainPanel:= TPanel.Create(<span class="kw">Self</span>);</span>
366-<span id="cb1-40"><a href="#cb1-40" aria-hidden="true" tabindex="-1"></a> <span class="kw">with</span> (MainPanel) <span class="kw">do</span></span>
367-<span id="cb1-41"><a href="#cb1-41" aria-hidden="true" tabindex="-1"></a> <span class="kw">begin</span></span>
368-<span id="cb1-42"><a href="#cb1-42" aria-hidden="true" tabindex="-1"></a> Parent:= <span class="kw">Self</span>;</span>
369-<span id="cb1-43"><a href="#cb1-43" aria-hidden="true" tabindex="-1"></a> Align:= alClient;</span>
370-<span id="cb1-44"><a href="#cb1-44" aria-hidden="true" tabindex="-1"></a> Caption:= <span class="st">&#39;Hello&#39;</span>;</span>
371-<span id="cb1-45"><a href="#cb1-45" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span>;</span>
372-<span id="cb1-46"><a href="#cb1-46" aria-hidden="true" tabindex="-1"></a><span class="kw">end</span>;</span></code></pre></div></td>
373-<td class="code"><div class="sourceCode" id="cb2"><pre class="sourceCode pascal"><code class="sourceCode pascal"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span></span>
374-<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a> BottomPanel: TPanel;</span>
375-<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> VerticalSplitter: TPairSplitter;</span>
376-<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> LeftPanel: TPanel;</span>
377-<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a> HorizontalSplitter: TPairSplitter;</span>
378-<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> MainPanel: TPanel;</span>
379-<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a></span>
380-<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="kw">begin</span></span>
381-<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a> VerticalSplitter:= TPairSplitter.Create(<span class="kw">Self</span>);</span>
382-<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a> <span class="kw">with</span> (VerticalSplitter) <span class="kw">do</span></span>
383-<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a> <span class="kw">begin</span></span>
384-<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a> Parent:= <span class="kw">Self</span>;</span>
385-<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a> Align:= alClient;</span>
386-<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a> Width:= <span class="kw">Self</span>.Width;</span>
387-<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a> Height:= <span class="kw">Self</span>.Height;</span>
388-<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a> SplitterType:= pstVertical;</span>
389-<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a> Position:= Height - <span class="dv">75</span>;</span>
390-<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a> Sides[<span class="dv">0</span>].Width:= Width;</span>
391-<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a> Sides[<span class="dv">0</span>].Height:= Position;</span>
392-<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span>;</span>
393-<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a></span>
394-<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a> HorizontalSplitter:= TPairSplitter.Create(<span class="kw">Self</span>);</span>
395-<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a> <span class="kw">with</span> (HorizontalSplitter) <span class="kw">do</span></span>
396-<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a> <span class="kw">begin</span></span>
397-<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a> Parent:= VerticalSplitter.Sides[<span class="dv">0</span>];</span>
398-<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a> Width:= <span class="kw">Self</span>.Width;</span>
399-<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a> Height:= VerticalSplitter.Position;</span>
400-<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a> align:= alClient;</span>
401-<span id="cb2-29"><a href="#cb2-29" aria-hidden="true" tabindex="-1"></a> SplitterType:= pstHorizontal;</span>
402-<span id="cb2-30"><a href="#cb2-30" aria-hidden="true" tabindex="-1"></a> Position:= <span class="dv">125</span>;</span>
403-<span id="cb2-31"><a href="#cb2-31" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span>;</span>
404-<span id="cb2-32"><a href="#cb2-32" aria-hidden="true" tabindex="-1"></a></span>
405-<span id="cb2-33"><a href="#cb2-33" aria-hidden="true" tabindex="-1"></a> LeftPanel:= TPanel.Create(<span class="kw">Self</span>);</span>
406-<span id="cb2-34"><a href="#cb2-34" aria-hidden="true" tabindex="-1"></a> <span class="kw">with</span> (LeftPanel) <span class="kw">do</span></span>
407-<span id="cb2-35"><a href="#cb2-35" aria-hidden="true" tabindex="-1"></a> <span class="kw">begin</span></span>
408-<span id="cb2-36"><a href="#cb2-36" aria-hidden="true" tabindex="-1"></a> Parent:= HorizontalSplitter.Sides[<span class="dv">0</span>];</span>
409-<span id="cb2-37"><a href="#cb2-37" aria-hidden="true" tabindex="-1"></a> Align:= alClient;</span>
410-<span id="cb2-38"><a href="#cb2-38" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span>;</span>
411-<span id="cb2-39"><a href="#cb2-39" aria-hidden="true" tabindex="-1"></a></span>
412-<span id="cb2-40"><a href="#cb2-40" aria-hidden="true" tabindex="-1"></a> MainPanel:= TPanel.Create(<span class="kw">Self</span>);</span>
413-<span id="cb2-41"><a href="#cb2-41" aria-hidden="true" tabindex="-1"></a> <span class="kw">with</span> (MainPanel) <span class="kw">do</span></span>
414-<span id="cb2-42"><a href="#cb2-42" aria-hidden="true" tabindex="-1"></a> <span class="kw">begin</span></span>
415-<span id="cb2-43"><a href="#cb2-43" aria-hidden="true" tabindex="-1"></a> Parent:= HorizontalSplitter.Sides[<span class="dv">1</span>];</span>
416-<span id="cb2-44"><a href="#cb2-44" aria-hidden="true" tabindex="-1"></a> Align:= alClient;</span>
417-<span id="cb2-45"><a href="#cb2-45" aria-hidden="true" tabindex="-1"></a> Caption:= <span class="st">&#39;Hello&#39;</span>;</span>
418-<span id="cb2-46"><a href="#cb2-46" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span>;</span>
419-<span id="cb2-47"><a href="#cb2-47" aria-hidden="true" tabindex="-1"></a></span>
420-<span id="cb2-48"><a href="#cb2-48" aria-hidden="true" tabindex="-1"></a> BottomPanel:= TPanel.Create(<span class="kw">Self</span>);</span>
421-<span id="cb2-49"><a href="#cb2-49" aria-hidden="true" tabindex="-1"></a> <span class="kw">with</span> (BottomPanel) <span class="kw">do</span></span>
422-<span id="cb2-50"><a href="#cb2-50" aria-hidden="true" tabindex="-1"></a> <span class="kw">begin</span></span>
423-<span id="cb2-51"><a href="#cb2-51" aria-hidden="true" tabindex="-1"></a> Parent:= VerticalSplitter.Sides[<span class="dv">1</span>];</span>
424-<span id="cb2-52"><a href="#cb2-52" aria-hidden="true" tabindex="-1"></a> Align:= alClient;</span>
425-<span id="cb2-53"><a href="#cb2-53" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span>;</span>
426-<span id="cb2-54"><a href="#cb2-54" aria-hidden="true" tabindex="-1"></a><span class="kw">end</span>;</span></code></pre></div></td>
427-</tr>
428-</tbody>
429-</table>
320+**VCL**
430321
322+**LCL**
323+
324+``` pascal
325+var
326+ BottomPanel: TPanel;
327+ VerticalSplitter: TSplitter;
328+ LeftPanel: TPanel;
329+ HorizontalSplitter: TSplitter;
330+ MainPanel: TPanel;
331+
332+begin
333+ BottomPanel:= TPanel.Create(Self);
334+ with (BottomPanel) do
335+ begin
336+ Parent:= Self;
337+ Height:= 75;
338+ Align:= alBottom;
339+ end;
340+
341+ VerticalSplitter:= TSplitter.Create(Self);
342+ with (VerticalSplitter) do
343+ begin
344+ Parent:= Self;
345+ Align:= alBottom;
346+ end;
347+
348+ HorizontalSplitter:= TSplitter.Create(Self);
349+ with (HorizontalSplitter) do
350+ begin
351+ Parent:= Self;
352+ align:= alLeft;
353+ end;
354+
355+ LeftPanel:= TPanel.Create(Self);
356+ with (LeftPanel) do
357+ begin
358+ Parent:= Self;
359+ Width:= 125;
360+ Align:= alLeft;
361+ end;
362+
363+ MainPanel:= TPanel.Create(Self);
364+ with (MainPanel) do
365+ begin
366+ Parent:= Self;
367+ Align:= alClient;
368+ Caption:= 'Hello';
369+ end;
370+end;
371+```
372+
373+``` pascal
374+var
375+ BottomPanel: TPanel;
376+ VerticalSplitter: TPairSplitter;
377+ LeftPanel: TPanel;
378+ HorizontalSplitter: TPairSplitter;
379+ MainPanel: TPanel;
380+
381+begin
382+ VerticalSplitter:= TPairSplitter.Create(Self);
383+ with (VerticalSplitter) do
384+ begin
385+ Parent:= Self;
386+ Align:= alClient;
387+ Width:= Self.Width;
388+ Height:= Self.Height;
389+ SplitterType:= pstVertical;
390+ Position:= Height - 75;
391+ Sides[0].Width:= Width;
392+ Sides[0].Height:= Position;
393+ end;
394+
395+ HorizontalSplitter:= TPairSplitter.Create(Self);
396+ with (HorizontalSplitter) do
397+ begin
398+ Parent:= VerticalSplitter.Sides[0];
399+ Width:= Self.Width;
400+ Height:= VerticalSplitter.Position;
401+ align:= alClient;
402+ SplitterType:= pstHorizontal;
403+ Position:= 125;
404+ end;
405+
406+ LeftPanel:= TPanel.Create(Self);
407+ with (LeftPanel) do
408+ begin
409+ Parent:= HorizontalSplitter.Sides[0];
410+ Align:= alClient;
411+ end;
412+
413+ MainPanel:= TPanel.Create(Self);
414+ with (MainPanel) do
415+ begin
416+ Parent:= HorizontalSplitter.Sides[1];
417+ Align:= alClient;
418+ Caption:= 'Hello';
419+ end;
420+
421+ BottomPanel:= TPanel.Create(Self);
422+ with (BottomPanel) do
423+ begin
424+ Parent:= VerticalSplitter.Sides[1];
425+ Align:= alClient;
426+ end;
427+end;
428+```
429+
431430So as you can see, farely consistant with most control hierarchy. And if you are familiar with DFM's, the changes needed for DFM-\>LFM conversion should be farely obvious from the above, as they are the same sort of changes in Parent/Owner etc.
432431
433432So the above example would be something like -
434433
435-<table>
436-<tbody>
437-<tr>
438-<td class="header"><p><strong>Delphi DFM</strong></p>
439-<div style="font-weight: normal">
440-<p><strong>(extraneous values removed)</strong></p></td>
441-<td class="header"><p><strong>Lazarus LFM</strong></p>
442-<div style="font-weight: normal">
443-<p><strong>(most width, height, etc. removed)</strong></p></td>
444-</tr>
445-<tr>
446-<td class="code"><div class="sourceCode" id="cb1"><pre class="sourceCode pascal"><code class="sourceCode pascal"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">object</span> VerticalSplitter: TSplitter</span>
447-<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a> Height = <span class="dv">3</span></span>
448-<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> Cursor = crVSplit</span>
449-<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a> Align = alBottom</span>
450-<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">end</span></span>
451-<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="kw">object</span> HorizontalSplitter: TSplitter</span>
452-<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a> Width = <span class="dv">3</span></span>
453-<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a> Align = alLeft</span>
454-<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="kw">end</span></span>
455-<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="kw">object</span> BottomPanel: TPanel</span>
456-<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a> Height = <span class="dv">75</span></span>
457-<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a> Align = alBottom</span>
458-<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="kw">end</span></span>
459-<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="kw">object</span> LeftPanel: TPanel</span>
460-<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a> Width = <span class="dv">125</span></span>
461-<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a> Align = alLeft</span>
462-<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="kw">end</span></span>
463-<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a><span class="kw">object</span> MainPanel: TPanel</span>
464-<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a> Align = alClient</span>
465-<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a><span class="kw">end</span></span></code></pre></div></td>
466-<td class="code"><div class="sourceCode" id="cb2"><pre class="sourceCode pascal"><code class="sourceCode pascal"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">object</span> VerticalSplitter: TPairSplitter</span>
467-<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a> Align = alClient</span>
468-<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> SplitterType = pstVertical</span>
469-<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> Position = <span class="dv">225</span></span>
470-<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a> Height = <span class="dv">300</span></span>
471-<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> Width = <span class="dv">400</span></span>
472-<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a> <span class="kw">object</span> Pairsplitterside1: TPairSplitterIde</span>
473-<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a> <span class="kw">object</span> HorizontalSplitter: TPairSplitter</span>
474-<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a> Align = alClient</span>
475-<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a> Position = <span class="dv">125</span></span>
476-<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a> <span class="kw">object</span> Pairsplitterside3: TPairSplitterIde</span>
477-<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a> Width = <span class="dv">125</span></span>
478-<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a> <span class="kw">object</span> LeftPanel: TPanel</span>
479-<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a> Align = alClient</span>
480-<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a> Width = <span class="dv">125</span></span>
481-<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
482-<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
483-<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a> <span class="kw">object</span> Pairsplitterside4: TPairSplitterIde</span>
484-<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a> <span class="kw">object</span> MainPanel: TPanel</span>
485-<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a> Align = alClient</span>
486-<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
487-<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
488-<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
489-<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
490-<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a> <span class="kw">object</span> Pairsplitterside2: TPairSplitterIde</span>
491-<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a> <span class="kw">object</span> BottomPanel: TPanel</span>
492-<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a> Align = alClient</span>
493-<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a> Height = <span class="dv">75</span></span>
494-<span id="cb2-29"><a href="#cb2-29" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
495-<span id="cb2-30"><a href="#cb2-30" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
496-<span id="cb2-31"><a href="#cb2-31" aria-hidden="true" tabindex="-1"></a><span class="kw">end</span></span></code></pre></div></td>
497-</tr>
498-</tbody>
499-</table>
434+**Delphi DFM**
435+
436+**(extraneous values removed)**
437+
438+**Lazarus LFM**
439+
440+**(most width, height, etc. removed)**
441+
442+``` pascal
443+object VerticalSplitter: TSplitter
444+ Height = 3
445+ Cursor = crVSplit
446+ Align = alBottom
447+end
448+object HorizontalSplitter: TSplitter
449+ Width = 3
450+ Align = alLeft
451+end
452+object BottomPanel: TPanel
453+ Height = 75
454+ Align = alBottom
455+end
456+object LeftPanel: TPanel
457+ Width = 125
458+ Align = alLeft
459+end
460+object MainPanel: TPanel
461+ Align = alClient
462+end
463+```
464+
465+``` pascal
466+object VerticalSplitter: TPairSplitter
467+ Align = alClient
468+ SplitterType = pstVertical
469+ Position = 225
470+ Height = 300
471+ Width = 400
472+ object Pairsplitterside1: TPairSplitterIde
473+ object HorizontalSplitter: TPairSplitter
474+ Align = alClient
475+ Position = 125
476+ object Pairsplitterside3: TPairSplitterIde
477+ Width = 125
478+ object LeftPanel: TPanel
479+ Align = alClient
480+ Width = 125
481+ end
482+ end
483+ object Pairsplitterside4: TPairSplitterIde
484+ object MainPanel: TPanel
485+ Align = alClient
486+ end
487+ end
488+ end
489+ end
490+ object Pairsplitterside2: TPairSplitterIde
491+ object BottomPanel: TPanel
492+ Align = alClient
493+ Height = 75
494+ end
495+ end
496+end
497+```
500498
501499### TCustomTreeView/TTreeView
502500
503501Both VCL and the LCL provide a TCustomTreeView/TTreeView component, used for tree structured lists of data with multiple nodes and advanced selection and Image lists, and while actual features are comparable, not all properties are entirely compatible. Primary differences are as follows -
504502
505503**Incomplete list, also update to include TCustomTreeView Mark functions and protected methods**
506504
5075051. The LCL provides a TCustomTreeView.Options, a set of options which can be set on the control to change its behaviour and apearance. These options are :
508506 - tvoAllowMultiselect - enables multi node select mode, equivalent to enabling TCustomTreeView.MultiSelect in the D6 VCL
509507 - tvoAutoExpand - Auto Expand nodes, equivalent to enabling TCustomTreeView.AutoExpand
510508 - tvoAutoInsertMark - Update the Drag preview on mouse move.
511509 - tvoAutoItemHeight - Adjust the item heights automatically.
512510 - tvoHideSelection - Do not mark the selected item.
513511 - tvoHotTrack - use Hot Tracking, equivalent to enabling TCustomTreeview.HotTrack
514512 - tvoKeepCollapsedNodes - When shrinking/folding nodes, keep the child nodes
515513 - tvoReadOnly - make Treeview read only, equivalent to enabling TCustomTreeview.ReadOnly
516514 - tvoRightClickSelect - allow using Mouse Right Clicks to select nodes, equivalent to enabling TCustomTreeView.RightClickSelect
517515 - tvoRowSelect - allow selecting rows, equivalent to enabling TCustomTreeView.RowSelect
518516 - tvoShowButtons - show buttons, equivalent to enabling TCustomTreeView.ShowButtons
519517 - tvoShowLines - show node lines, equivalent to enabling TCustomTreeView.ShowLines
520518 - tvoShowRoot - show root note, equivalent to enabling TCustomTreeView.ShowRoot
521519 - tvoShowSeparators - show seperators
522520 - tvoToolTips - show tooltips for individual nodes
5235212. The LCL provides additional properties:
524522 - TCustomTreeView.OnSelectionChange event
525523 - TCustomTreeView.DefaultItems, for the default number of Items
526524 - TCustomTreeView.ExpandSignType to determine sign used on expandable/collapsible nodes
5275253. While most On Drag/Dock Events are available in the LCL they do not work. For more information please see earlier section on Control Dragging/Docking.
528526
529527### Messages / Events
530528
531529The order and frequency of messages and events (OnShow, OnActivate, OnEnter, ...) differ from the VCL and depend on the [[Widgetset|widgetset]]. The LCL provides a subset of WinAPI like messages to make porting of Delphi components easier, but almost all LCL messages work a little bit different than the VCL/WinAPI counterpart. The biggest part of Delphi code using WinAPI messages uses them, because the VCL lacks a feature or for speed reasons. Such things will seldom work the same under the LCL, so they must be checked manually. That's why LCL messages are called for example LM_SIZE instead of WM_SIZE (unit lmessages).
532530
533531**Note on handling of custom messages!** As of version 0.9.26 (December 2008), way of handling custom WinApi messages (e.g. WM_HOTKEY, WM_SYSCOMMAND) differs from the way of handling these messages in Delphi. At the moment you cannot handle them via **message** directive or via overriding of *WndProc* method of the form. The only way to handle them in the form is to hook Windows *windowproc* by yourself. Read more here: [[Win32/64 Interface|Processing non-user messages in your window]]
534532
535533## See also
536534
537535- [[Delphi language features missing from the Free Pascal Compiler]]
538536- [[Code Conversion Guide|Code Conversion Guide (from Delphi &amp; Kylix)]]
539537- [[Compile With Delphi]]
540538
541539---
542540*From the Free Pascal wiki, page "Lazarus For Delphi Users", as it stood on 2022-05-31 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history