Sign in Join
Wiki copytemporary

Lazarus For Delphi Users/ru: what changed

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

OldNewLine
11Эта статья предназначена для тех, кто интересуется Lazarus и уже знает Delphi. Здесь описаны различия между ними.
22
33## Delphi -\> Lazarus
44
55Lazarus - среда быстрой разработки приложений (RAD), как и Delphi. Это значит, что она состоит из библиотеки визуальных компонентов и среды разработки (IDE). Библиотека компонентов Lazarus (LCL) похожа на библиотеку визуальных компонентов Delphi (VCL). Большинство модулей, классов и свойств Lazarus обладают такими же именами и функциями, как их аналоги в Delphi. Это делает относительно лёгким перенос приложений Delphi в Lazarus. Однако Lazarus **не является** 'клоном Delphi с открытым кодом', поэтому не следует ожидать 100%-ной совместимости.
66
77### Самые большие различия между Lazarus и Delphi
88
99- код Lazarus полностью открыт
1010- Lazarus написан кроссплатформенным способом
1111- Lazarus использует компилятор [[Free Pascal]] (FPC)
1212
1313FPC работает на 15 платформах. Однако не все пакеты и библиотеки FPC портированы на все платформы, поэтому Lazarus работает на:
1414
1515- Linux (i386, x86_64)
1616- FreeBSD (i386)
1717- macOS (powerpc, i386, x86_64)
1818- Windows (i386, x86_64)
1919
2020**Работа над Lazarus, как и над этим текстом, не закончена. Мы всё время ищем новых разработчиков и технических писателей...**
2121
2222### С чего начать перенос проекта Delphi в Lazarus
2323
2424В меню **Сервис** выберите команду **Преобразовать проект Delphi в проект Lazarus**. Не стоит ждать, что так будет преобразовано абсолютно всё, тем не менее, это хорошее начало. Учтите, что средства Lazarus выполняют, в основном, преобразования в одном направлении. Если вам надо сохранить совместимость с Delphi (компилировать проект и в Delphi, и в Lazarus) рассмотрите использование [[XDev Toolkit]].
2525
2626### Поддержка Юникода
2727
2828Delphi до версии 2007 не поддерживала Юникод, а использовала кодировку Windows ANSI. Юникод в кодировке UTF-16 поддерживается в Delphi с версии 2009.
2929
3030В Lazarus поддержка Юникод реализована раньше в кодировке UTF-8 (см. [[LCL Unicode Support/ru|Поддержка Юникод в LCL]]).
3131
3232## Delphi IDE -\> Lazarus IDE
3333
3434### Проекты
3535
3636Главным в приложении Delphi является файл .dpr. Файл .dpr также содержит главный код программы Delphi и является местом, где среда разработки Delphi хранит сведения о соответствующих ключах компилятора и нахождении модулей. В приложении Lazarus есть файл .lpr, который также является основным файлом кода проекта на языке Pascal. Тем не менее, главным в проекте Lazarus является файл .lpi (Lazarus Project Information), который создаётся вместе с файлом .lpr. Все данные проекта (ключи компилятора, пути к модулям и т.п.) хранятся в файле .lpi. Поэтому важнейшим является файл .lpi. На большинстве платформ двойной щелчок по файлу .lpi открывает проект в среде разработки Lazarus.
3737
3838Delphi хранит пути к модулям проекта в файле .dpr. Пример:
3939
4040`unit1 in 'path/Unit1.pas';`
4141
4242Такие пути со словом 'in' специфичны для Delphi, и не работают в Lazarus, поэтому не используйте их. Вместо этого в параметрах проекта (**Проект-\>Параметры проекта...**) на странице **Параметры компилятора-\>Пути** задайте пути к модулям, находящимся за пределами каталога проекта. Большинство путей к модулям задаются автоматически после добавления зависимости от какого-либо пакета. Например, во все стандартные проекты Lazarus LCL по умолчанию добавляется зависимость от пакета LCL, поэтому в каждом новом проекте Lazarus LCL (**Проект-\>Создать проект...-\>Приложение**) пути ко всем модулям LCL известны без вашего участия.
4343
4444Delphi хранит параметры компилятора в файле .dpr (например, {\$APPTYPE CONSOLE}). Lazarus игнорирует такую запись. Вместо этого используйте страницу **Параметры компилятора** в диалоге **Параметры проекта**.
4545
4646### Среда Lazarus не бывает "пустой"
4747
4848В среде Lazarus всегда открыт проект. Единственный способ "закрыть" проект - выход из Lazarus или открытие другого проекта. Это связано с тем, что проект Lazarus - ещё и "сеанс работы". Сведения о сеансе (например, параметры редактора) также хранятся в файле .lpi, и при повторном открытии проекта состояние редактора восстанавливается.
4949
5050**Пример.** Вы отлаживаете приложение и расставили несколько точек останова и закладок. Вы можете в любой момент сохранить проект, закрыть Lazarus или открыть другой проект. При повторном открытии проекта (даже на другом компьютере) все точки останова, закладки, открытые файлы, положение курсора, история переходов будут восстановлены.
5151
5252### Редактор исходного кода
5353
5454В меню Сервис -\> Параметры -\> Редактор -\> Комбинации клавиш могут быть заданы практически любые комбинации клавиш.
5555
5656Среда разработки Lazarus располагает множеством инструментов для работы с кодом. Многие из них выглядят и работают так же, как и в Delphi. Но есть одно важное отличие: Lazarus не использует компилятор для получения сведений о коде, а работает с ним напрямую. Это даёт ряд важных преимуществ:
5757
5858Редактор работает с "комментариями". В Delphi комментарии это просто место между фрагментами кода. Здесь не действуют никакие средства работы с кодом, и комментарии смещаются при автоматической вставке нового кода. В Lazarus можно найти объявление даже в закоментированном коде. Это не очень надёжно, однако работает в большинстве случаев. При вставке нового кода среда разработки использует некоторую эвристику, чтобы сохранить комментарий и код вместе. К примеру, строка `"c: char; // comment"` разделяться не будет.
5959
60-Дельфийское «Автозавершение кода» (<span class="kbd">Ctrl</span> + <span class="kbd">Space</span>) в Lazarus называется «Автозавершение идентификатора». Термин Lazarus'овское «Автозавершение кода» - это функция, объединяющая «Автоматическое завершение класса» (как в Delphi), «Автозавершение локальной переменной» и «Автозавершение назначения события». Все они вызываются по <span class="kbd">Ctrl</span> + <span class="kbd">Space</span> + <span class="kbd">C</span>, что подразумевает, что среда IDE определяет положение курсора.
60+Дельфийское «Автозавершение кода» (`Ctrl` + `Space`) в Lazarus называется «Автозавершение идентификатора». Термин Lazarus'овское «Автозавершение кода» - это функция, объединяющая «Автоматическое завершение класса» (как в Delphi), «Автозавершение локальной переменной» и «Автозавершение назначения события». Все они вызываются по `Ctrl` + `Space` + `C`, что подразумевает, что среда IDE определяет положение курсора.
6161
6262#### Пример для автозавершения локальной переменной
6363
6464Предположим, вы только что создали новый метод и написали оператор "i:=3;"
6565
6666``` pascal
6767procedure TForm1.DoSomething;
6868begin
6969 i := 3;
7070end;
7171```
7272
73-Наведите курсор на идентификатор «i» и нажмите <span class="kbd">Ctrl</span>+<span class="kbd">Shift</span>+<span class="kbd">C</span>, чтобы получить:
73+Наведите курсор на идентификатор «i» и нажмите `Ctrl`+`Shift`+`C`, чтобы получить:
7474
7575``` pascal
7676procedure TForm1.DoSomething;
7777var i: Integer;
7878begin
7979 i := 3;
8080end;
8181```
8282
8383#### Пример автозавершения назначения события
8484
8585Приятной особенностью инспектора объектов является автоматическое создание методов. Заодно, вы можете получить редактор исходного кода для создания событий.\
8686Например:
8787
8888``` pascal
8989Button1.OnClick:=
9090```
9191
92-Поместите курсор за оператором присваивания ":=" и нажмите <span class="kbd">Ctrl</span>+<span class="kbd">Shift</span>+<span class="kbd">C</span>.
92+Поместите курсор за оператором присваивания ":=" и нажмите `Ctrl`+`Shift`+`C`.
9393
9494------------------------------------------------------------------------
9595
9696Прим.перев.: при этом сформированный код будет выглядеть так:
9797
9898``` pascal
9999procedure TForm1.FormCreate(Sender: TObject);
100100begin
101101 Button1.OnClick:=@Button1Click;
102102end;
103103
104104procedure TForm1.Button1Click(Sender: TObject);
105105begin
106106
107107end;
108108```
109109
110110#### Пример автозавершения вызова процедуры
111111
112112Предположим, вы только что написали оператор "DoSomething(Width);"
113113
114114``` pascal
115115procedure SomeProcedure;
116116var
117117 Width: integer;
118118begin
119119 Width:=3;
120120 DoSomething(Width);
121121end;
122122```
123123
124-Наведите курсор на идентификатор «DoSomething» и нажмите <span class="kbd">Ctrl</span>+<span class="kbd">Shift</span>+<span class="kbd">C</span>, чтобы получить:
124+Наведите курсор на идентификатор «DoSomething» и нажмите `Ctrl`+`Shift`+`C`, чтобы получить:
125125
126126``` pascal
127127procedure DoSomething(aWidth: LongInt);
128128begin
129129
130130end;
131131
132132procedure SomeProcedure;
133133var
134134 Width: integer;
135135begin
136136 Width:=3;
137137 DoSomething(Width);
138138end;
139139```
140140
141141#### "Автозавершение слова" Ctrl+W
142142
143143Он работает аналогично «Автозавершению идентификатора», но работает не для идентификаторов паскалей, а для всех слов. Позволяет выбрать все слова во всех открытых файлах, начиная с одинаковых букв.
144144
145145#### Поддержка Include-файлов
146146
147147Delphi не поддерживал их, поэтому вы, вероятно, еще не создавали много включаемых файлов. Но у включаемых файлов есть большое преимущество: они позволяют писать (не)зависимый от платформы код, не запутывая ваш код IFDEF'ами. Например: переход по методу, автозавершение класса, объявление find, ... все работает с include-файлами.
148148
149149Есть много вариантов функций кода.
150150
151151### Designer
152152
153153\- см. руководство пользователя
154154
155155#### Инспектор объектов
156156
157157В IDE Delphi и IDE Lazarus'а Инспектор объектов используется для редактирования свойств компонента, назначения событий и т.д. Ниже приведены некоторые незначительные отличия, которые следует отметить при использовании:
158158
1591591. Начиная с Delphi 5, существует Дерево Объектов(Object Treeview), которое можно использовать для навигации и выбора объектов в соответствии с иерархией в дополнение к традиционному выпадающему списку в Инспекторе объектов. В Lazarus это является частью Инспектора объектов и используется вместо раскрывающегося списка по умолчанию, вы можете выбрать его из контекстного меню "Show Component Tree"(Показать дерево компонентов), чтобы использовать/не использовать.
1601602. В Delphi двойной щелчок на пустом событии автоматически создаст его и откроет редактор исходного кода в этой позиции, в Lazarus справа от выбранного выпадающего меню есть кнопка, которая выполняет это действие.
1611613. В Delphi вы должны вручную удалить имя события в редакторе, чтобы удалить привязку к нему, в Lazarus вы можете нажать на раскрывающийся список и выбрать "(None)"(Нет).
1621624. Двойной щелчок по обычным свойствам, таким как логическое значение, не изменит его значение (как это произошло бы случае с Events(Событием)), вы должны выбрать его из выпадающего списка. А чтобы открыть их с прилагаемой формой редактора, вы должны нажать кнопку «...» справа от раскрывающегося меню.
163163
164164#### Пакеты
165165
166166- Может ли Lazarus установить и использовать пакеты Delphi?
167167
168168
169169Нет, потому что они требуют магии компилятора Delphi.
170170
171171- Должны ли они быть специально сделанными для Lazarus?
172172
173173
174174Да.
175175
176176Создайте новый пакет, сохраните его в каталоге с исходниками пакета (обычно это тот же каталог файла .dpk), добавьте LCL как требуемый пакет и, наконец, добавьте файлы .pas. Теперь вы можете установить его или использовать в своих проектах. Есть некоторые [[packages|различия между пакетами Lazarus и Delphi]].
177177
178178## VCL -\> LCL
179179
180180Хотя VCL и LCL служат большей части одной и той же цели - объектно-ориентированной иерархии компонентов, особенно ориентированной на быструю разработку приложений, они не идентичны. Например, в то время как VCL предоставляет много невизуальных компонентов, LCL пытается предоставлять только визуальные, в то время как большинство невизуальных компонентов (таких как доступ к базе данных) предоставляются с FCL, включенным в [[Free Pascal]].
181181
182182Кроме того, многие элементы управления, которые представлены в VCL, могут отсутствовать в LCL, или наоборот, или даже если элементы управления существуют в обоих, они не являются клонами, и при переносе необходимо внести изменения в приложения, компоненты и элементы управления.
183183
184184Ниже приведена попытка для пользователя Delphi дать достаточно полное описание основных различий или несовместимостей между ними. Она охватывает различия в первую очередь особенно для VCL D4, хотя иногда также D5, D6 или D7; и с текущим LCL, как в CVS. Таким образом, оно может не всегда соответствовать версии Delphi, к которой вы привыкли, или полностью соответствовать текущему LCL, который у вас есть. Если вы видите неточности между нижеследующим и LCL, как в CVS, или ваш Delphi не стесняется добавлять и изменять, чтобы сделать его максимально полным для всех людей.
185185
186186### TControl.Font/TControl.ParentFont
187187
188188В VCL довольно распространено и нормально использовать определенное имя шрифта и свойства шрифта, такие как жирный шрифт и курсив для элементов управления, и ожидать, что это значение всегда будет соблюдаться. Далее предоставляется свойство TControl.ParentFont, которое гарантирует, что элемент управления всегда будет следовать за шрифтом его родителя. Опять же подразумеваемое предположение, что эти значения будут всегда соблюдаться, даже независимо от настроек внешнего вида Windows.
189189
190190Это не всегда верно в LCL, да и не может быть. LCL, являющийся кросс-платформой/кросс-интерфейсом по своей природе, предпочитает сбалансированный подход и вместо этого всегда будет пытаться использовать собственные настройки Рабочего стола/Внешнего вида инструментария или Темы для любых виджетов. Например, если используется интерфейс GTK, а тема gtk предоставляет определенный шрифт для кнопок, то кнопки LCL всегда будут пытаться использовать этот шрифт.
191191
192192Это означает, что большинство элементов управления LCL не имеют того же уровня управления проектированием, который часто ожидается в VCL, скорее, только те пользовательские элементы управления, которые нарисованы Canvas вместо назначенного интерфейса, могут постоянно изменяться таким образом независимо от используемого интерфейса.
193193
194194### Control Dragging/Docking
195195
196196В VCL большинство (Win)Controls реализуют методы и функции обратного вызова для обработки перетаскивания и закрепления элементов управления, например, перетаскивая элемент управления с одной панели и закрепляя его на другой панели во время выполнения.
197197
198198Эта функциональность в настоящее время не реализована/не завершена в LCL, хотя в настоящее время она находится на начальных этапах планирования и должна в конечном итоге поддерживать некоторый уровень совместимости для этого типа поведения, если не точно таким же образом.
199199
200200В настоящее время это означает, что ни один элемент управления не будет наследовать/использовать следующие функции, процедуры, свойства или события TControl:
201201
202202``` pascal
203203Protected
204204 function GetDockEdge(MousePos: TPoint): TAlign;
205205 function GetDragImages: TDragImageList;
206206 function GetFloating: Boolean;
207207 function GetFloatingDockSiteClass: TWinControlClass;
208208 procedure DoEndDrag(Target:TObject); X, Y: Integer);
209209 procedure DockTrackNoTarget(Source: TDragDockObject; X, Y: Integer);
210210 procedure DoEndDock(Target: TObject; X, Y: Integer);
211211 procedure DoDock(NewDockSite: TWinControl; var ARect: TRect);
212212 procedure DoStartDock(var DragObject: TDragObject);
213213 procedure DragCanceled;
214214 procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState;
215215 var Accept: Boolean);
216216 procedure DoEndDrag(Target: TObject; X, Y: Integer);
217217 procedure DoStartDrag(var DragObject: TDragObject);
218218 procedure DrawDragDockImage(DragDockObject: TDragDockObject);
219219 procedure EraseDragDockImage(DragDockObject: TDragDockObject);
220220 procedure PositionDockRect(DragDockObject: TDragDockObject);
221221 procedure SetDragMode(Value: TDragMode);
222222 property DragKind: TDragKind;
223223 property DragCursor: TCursor;
224224 property DragMode: TDragMode;
225225 property OnDragDrop: TDragDropEvent;
226226 property OnDragOver: TDragOverEvent;
227227 property OnEndDock: TEndDragEvent;
228228 property OnEndDrag: TEndDragEvent;
229229 property OnStartDock: TStartDockEvent;
230230 property OnStartDrag: TStartDragEvent;
231231public
232232 function Dragging: Boolean;
233233 function ManualDock(NewDockSite: TWinControl; DropControl: TControl;
234234 ControlSide: TAlign): Boolean;
235235 function ManualFloat(ScreenPos: TRect): Boolean;
236236 function ReplaceDockedControl(Control: TControl; NewDockSite: TWinControl;
237237 DropControl: TControl; ControlSide: TAlign): Boolean;
238238 procedure BeginDrag(Immediate: Boolean; Threshold: Integer);
239239 procedure Dock(NewDockSite: TWinControl; ARect: TRect);
240240 procedure DragDrop(Source: TObject; X, Y: Integer);
241241 procedure EndDrag(Drop: Boolean);
242242 property DockOrientation: TDockOrientation;
243243 property Floating: Boolean;
244244 property FloatingDockSiteClass: TWinControlClass;
245245 property HostDockSite: TWinControl;
246246 property LRDockWidth: Integer;
247247 property TBDockHeight: Integer;
248248 property UndockHeight: Integer;
249249 property UndockWidth: Integer;
250250```
251251
252252Вот эти классы не существуют/непригодны для использования -
253253
254254``` pascal
255255TDragImageList = class(TCustomImageList)
256256TDockZone = class
257257TDockTree = class(TInterfacedObject, IDockManager)
258258TDragObject = class(TObject)
259259TBaseDragControlObject = class(TDragObject)
260260TDragControlObject = class(TBaseDragControlObject)
261261TDragDockObject = class(TBaseDragControlObject)
262262```
263263
264264а вот эти функции также непригодны / несовместимы -
265265
266266``` pascal
267267function FindDragTarget(const Pos: TPoint;
268268 AllowDisabled: Boolean) : TControl;
269269procedure CancelDrag;
270270function IsDragObject(sender: TObject): Boolean;
271271```
272272
273273Запуск менеджера пристыковки окон описан здесь: [[Anchor Docking]]
274274
275275### TEdit/TCustomEdit
276276
277277Элементы управления Edit, хотя они и функционируют в основном как в LCL, так и в VCL, имеют некоторые особенности, которые необходимо учитывать при преобразовании:
278278
2792791. Из-за ограничений в интерфейсах TEdit.PasswordChar работает пока не во всех интерфейсах (хотя со временем может и будет), вместо этого следует использовать TCustomEdit.EchoMode emPassword в том случае, если текст события должен быть скрыт.
2802802. Событие Drag/Dock еще не реализовано. Для получения дополнительной информации см. предыдущий раздел Control Dragging/Docking.
2812813. Свойства шрифта обычно игнорируются для согласованности интерфейса, для подробного объяснения, что и как, пожалуйста, см. TControl.Font/TControl.ParentFont
282282
283283### TDBImage
284284
285285Delphi и Lazarus имеют элемент управления [[TDBImage]], который показывает изображения, хранящиеся в поле базы данных. В текущих стабильных версиях (1.2.4) Lazarus хранит информацию о типе изображения в поле базы данных перед фактическими данными изображения. См. процедуру *TDBImage.UpdateData*. Это означает, что Delphi и более старые реализации Lazarus не совместимы.
286286
287287В текущей стабильной версии Lazarus (1.2.0+) реализованы изменения, позволяющие использовать поведение, совместимое с Delphi. Пожалуйста, см. [[Lazarus 1.2.0 release notes|Lazarus_1.2.0_release_notes#TDBImage]] для получения подробной информации о том, как активировать это.
288288
289289Текущий транк Lazarus'а возвращается к Delphi-совместимому поведению при чтении полей базы данных в формате Delphi в TDBImage.
290290
291291### (необязательно) TSplitter -\> TPairSplitter
292292
293293**Пожалуйста, улучшите меня!**
294294
295295Теперь в LCL есть элемент управления [[TSplitter/ru|TSplitter]], поэтому нет необходимости его преобразовывать.
296296
297297Тем не менее, если вы хотите, здесь приводится объяснение:
298298
299299Следующее в основном основано на вопросах пользователя Vincent Snijders в списках рассылки и ответов [Andrew Johnson](http://lazarus-ccr.sourceforge.net/index.php?wiki=AndrewJohnson):
300300
301301В VCL элементы управления "Splitting" - это ползунок, который можно перетаскивать между двумя компонентами для предоставления большего или меньшего пространства одному из них за счет другого; выполняется \[посредством компонента\] TSplitter. Например, в IDE Delphi его можно увидеть между закрепленным Code Explorer и Source Viewer.
302302
303303LCL предоставляет свой собственный элемент управления, называемый [[TPairSplitter/ru|TPairSplitter]], который служит для тех же целей, однако он не совместим с Delphi, поэтому в случае переноса кода потребуется исправление "поврежденного" кода VCL или DFM-файлов Delphi, даже если используется много общего между двумя этими компонентами.
304304
305305Так в чем именно различия?
306306
307307Ну, самые большие различия в том, что VCL TSplitter не имеет \[размещенных на нем\] дочерних элементов, вместо этого он помещается между двумя правильно выровненными элементами управления и позволяет изменять их размер во время выполнения независимо от его собственного размера. На каждой стороне должно быть два элемента управления, чтобы что-нибудь сделать. Простым примером будет форма с выровненной по левому краю панелью, выровненным по левому краю разделителем и второй выровненной по клиенту панелью. Во время выполнения вы можете затем изменить размер, заданный для каждой панели, перетаскивая за специальный ползунок, предоставляемый элементом управления Splitter.
308308
309309Однако с точки зрения LCL, TPairSplitter - это особый вид управления с двумя панелями, и он может быть полезен только в том случае, если элементы управления для разделения находятся на этих панелях, но он все равно будет выполнять разбиение между этими панелями, независимо от того, что расположено на них. Таким образом, по аналогии с предыдущим примером, вы получите форму с выровненным клиентом TPairSplitter, выровненным по панели клиентом с левой стороны и выровненным по панели клиентом с правой стороны.
310310
311311------------------------------------------------------------------------
312312
313313Прим.перев.: иными словами, TPairSplitter - это готовый контейнер, разделенный TSplitter на две половины (в зависимости от значения свойства SplitterType на левую/правую или верхнюю/нижнюю), каждая из которых уже имеет привязку alClient, готова принимать на себя дочерние элементы и меняет свои размеры при перемещении ползунка разделителя.
314314
315315------------------------------------------------------------------------
316316
317317Другое важное отличие состоит в том, что в VCl, поскольку TSplitter является собственным TControl, положение сохраняется относительно других элементов управления при изменении размера. Поэтому, например, клиентская панель будет расти, в то время как другие панели этого делать не будут, таким образом, позиция разделения является относительна к выравниванию разделяемых элементов управления.
318318
319319В LCL, поскольку боковые панели отделены друг от друга, у TPairSplitter есть свойство Position, которое является абсолютным по отношению к верхнему или левому краям \[родительского элемента\]. Поэтому при изменении размера фактическая позиция не изменяется в зависимости от содержимого, отсюда, необходимо установить обратный вызов, чтобы обеспечить сохранение соотношения при изменении размера, если это важно.
320320
321321------------------------------------------------------------------------
322322
323323Прим.перев.: проще говоря, Position - это позиция ползунка TPairSplitter относительно левого/верхнего края контейнера (в зависимости от значения SplitterType = pstHorizontal/pstVertical соответственно).
324324
325325------------------------------------------------------------------------
326326
327327Например, если правая сторона вертикального разбиения должна иметь поведение, аналогичное alClient, необходимо добавить обратный вызов изменения размера формы, который выполняет что-то вроде:
328328
329329``` pascal
330330 PairSplitter.Position := PairSplitter.Width - PairSplitter.Position;
331331```
332332
333333Итак, как я могу преобразовать существующий код, использующий TSplitter, в TPairSplitter?
334334
335335Если разделитель и элементы управления создаются внутри фактической функции (например, при создании формы), преобразование не должно быть слишком сложным, в первую очередь реорганизуйте код, чтобы создать элементы управления в порядке новой иерархии, и установите родительские элементы дочерних элементов управления для разделения на левую/верхнюю и правую/нижнюю части PairSplitter. Пример изменений:
336336
337-<table>
338-<tbody>
339-<tr>
340-<td class="header"><p><strong>VCL</strong></p></td>
341-<td class="header"><p><strong>LCL</strong></p></td>
342-</tr>
343-<tr>
344-<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>
345-<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a> BottomPanel: TPanel;</span>
346-<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> VerticalSplitter: TSplitter;</span>
347-<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a> LeftPanel: TPanel;</span>
348-<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a> HorizontalSplitter: TSplitter;</span>
349-<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a> MainPanel: TPanel;</span>
350-<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
351-<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="kw">begin</span></span>
352-<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a> BottomPanel:= TPanel.Create(<span class="kw">Self</span>);</span>
353-<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>
354-<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a> <span class="kw">begin</span></span>
355-<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a> Parent:= <span class="kw">Self</span>;</span>
356-<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a> Height:= <span class="dv">75</span>;</span>
357-<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a> Align:= alBottom;</span>
358-<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span>;</span>
359-<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a></span>
360-<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a> VerticalSplitter:= TSplitter.Create(<span class="kw">Self</span>);</span>
361-<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>
362-<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a> <span class="kw">begin</span></span>
363-<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a> Parent:= <span class="kw">Self</span>;</span>
364-<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a> Align:= alBottom;</span>
365-<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span>;</span>
366-<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a></span>
367-<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a> HorizontalSplitter:= TSplitter.Create(<span class="kw">Self</span>);</span>
368-<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>
369-<span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a> <span class="kw">begin</span></span>
370-<span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a> Parent:= <span class="kw">Self</span>;</span>
371-<span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a> align:= alLeft;</span>
372-<span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span>;</span>
373-<span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a></span>
374-<span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a> LeftPanel:= TPanel.Create(<span class="kw">Self</span>);</span>
375-<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>
376-<span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a> <span class="kw">begin</span></span>
377-<span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a> Parent:= <span class="kw">Self</span>;</span>
378-<span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a> Width:= <span class="dv">125</span>;</span>
379-<span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a> Align:= alLeft;</span>
380-<span id="cb1-37"><a href="#cb1-37" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span>;</span>
381-<span id="cb1-38"><a href="#cb1-38" aria-hidden="true" tabindex="-1"></a></span>
382-<span id="cb1-39"><a href="#cb1-39" aria-hidden="true" tabindex="-1"></a> MainPanel:= TPanel.Create(<span class="kw">Self</span>);</span>
383-<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>
384-<span id="cb1-41"><a href="#cb1-41" aria-hidden="true" tabindex="-1"></a> <span class="kw">begin</span></span>
385-<span id="cb1-42"><a href="#cb1-42" aria-hidden="true" tabindex="-1"></a> Parent:= <span class="kw">Self</span>;</span>
386-<span id="cb1-43"><a href="#cb1-43" aria-hidden="true" tabindex="-1"></a> Align:= alClient;</span>
387-<span id="cb1-44"><a href="#cb1-44" aria-hidden="true" tabindex="-1"></a> Caption:= <span class="st">&#39;Привет&#39;</span>;</span>
388-<span id="cb1-45"><a href="#cb1-45" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span>;</span>
389-<span id="cb1-46"><a href="#cb1-46" aria-hidden="true" tabindex="-1"></a><span class="kw">end</span>;</span></code></pre></div></td>
390-<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>
391-<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a> BottomPanel: TPanel;</span>
392-<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> VerticalSplitter: TPairSplitter;</span>
393-<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> LeftPanel: TPanel;</span>
394-<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a> HorizontalSplitter: TPairSplitter;</span>
395-<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> MainPanel: TPanel;</span>
396-<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a></span>
397-<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="kw">begin</span></span>
398-<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a> VerticalSplitter:= TPairSplitter.Create(<span class="kw">Self</span>);</span>
399-<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>
400-<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a> <span class="kw">begin</span></span>
401-<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a> Parent:= <span class="kw">Self</span>;</span>
402-<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a> Align:= alClient;</span>
403-<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a> Width:= <span class="kw">Self</span>.Width;</span>
404-<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a> Height:= <span class="kw">Self</span>.Height;</span>
405-<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a> SplitterType:= pstVertical;</span>
406-<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a> Position:= Height - <span class="dv">75</span>;</span>
407-<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a> Sides[<span class="dv">0</span>].Width:= Width;</span>
408-<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a> Sides[<span class="dv">0</span>].Height:= Position;</span>
409-<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span>;</span>
410-<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a></span>
411-<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a> HorizontalSplitter:= TPairSplitter.Create(<span class="kw">Self</span>);</span>
412-<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>
413-<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a> <span class="kw">begin</span></span>
414-<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a> Parent:= VerticalSplitter.Sides[<span class="dv">0</span>];</span>
415-<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a> Width:= <span class="kw">Self</span>.Width;</span>
416-<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a> Height:= VerticalSplitter.Position;</span>
417-<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a> align:= alClient;</span>
418-<span id="cb2-29"><a href="#cb2-29" aria-hidden="true" tabindex="-1"></a> SplitterType:= pstHorizontal;</span>
419-<span id="cb2-30"><a href="#cb2-30" aria-hidden="true" tabindex="-1"></a> Position:= <span class="dv">125</span>;</span>
420-<span id="cb2-31"><a href="#cb2-31" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span>;</span>
421-<span id="cb2-32"><a href="#cb2-32" aria-hidden="true" tabindex="-1"></a></span>
422-<span id="cb2-33"><a href="#cb2-33" aria-hidden="true" tabindex="-1"></a> LeftPanel:= TPanel.Create(<span class="kw">Self</span>);</span>
423-<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>
424-<span id="cb2-35"><a href="#cb2-35" aria-hidden="true" tabindex="-1"></a> <span class="kw">begin</span></span>
425-<span id="cb2-36"><a href="#cb2-36" aria-hidden="true" tabindex="-1"></a> Parent:= HorizontalSplitter.Sides[<span class="dv">0</span>];</span>
426-<span id="cb2-37"><a href="#cb2-37" aria-hidden="true" tabindex="-1"></a> Align:= alClient;</span>
427-<span id="cb2-38"><a href="#cb2-38" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span>;</span>
428-<span id="cb2-39"><a href="#cb2-39" aria-hidden="true" tabindex="-1"></a></span>
429-<span id="cb2-40"><a href="#cb2-40" aria-hidden="true" tabindex="-1"></a> MainPanel:= TPanel.Create(<span class="kw">Self</span>);</span>
430-<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>
431-<span id="cb2-42"><a href="#cb2-42" aria-hidden="true" tabindex="-1"></a> <span class="kw">begin</span></span>
432-<span id="cb2-43"><a href="#cb2-43" aria-hidden="true" tabindex="-1"></a> Parent:= HorizontalSplitter.Sides[<span class="dv">1</span>];</span>
433-<span id="cb2-44"><a href="#cb2-44" aria-hidden="true" tabindex="-1"></a> Align:= alClient;</span>
434-<span id="cb2-45"><a href="#cb2-45" aria-hidden="true" tabindex="-1"></a> Caption:= <span class="st">&#39;Привет&#39;</span>;</span>
435-<span id="cb2-46"><a href="#cb2-46" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span>;</span>
436-<span id="cb2-47"><a href="#cb2-47" aria-hidden="true" tabindex="-1"></a></span>
437-<span id="cb2-48"><a href="#cb2-48" aria-hidden="true" tabindex="-1"></a> BottomPanel:= TPanel.Create(<span class="kw">Self</span>);</span>
438-<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>
439-<span id="cb2-50"><a href="#cb2-50" aria-hidden="true" tabindex="-1"></a> <span class="kw">begin</span></span>
440-<span id="cb2-51"><a href="#cb2-51" aria-hidden="true" tabindex="-1"></a> Parent:= VerticalSplitter.Sides[<span class="dv">1</span>];</span>
441-<span id="cb2-52"><a href="#cb2-52" aria-hidden="true" tabindex="-1"></a> Align:= alClient;</span>
442-<span id="cb2-53"><a href="#cb2-53" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span>;</span>
443-<span id="cb2-54"><a href="#cb2-54" aria-hidden="true" tabindex="-1"></a><span class="kw">end</span>;</span></code></pre></div></td>
444-</tr>
445-</tbody>
446-</table>
337+**VCL**
447338
339+**LCL**
340+
341+``` pascal
342+var
343+ BottomPanel: TPanel;
344+ VerticalSplitter: TSplitter;
345+ LeftPanel: TPanel;
346+ HorizontalSplitter: TSplitter;
347+ MainPanel: TPanel;
348+
349+begin
350+ BottomPanel:= TPanel.Create(Self);
351+ with (BottomPanel) do
352+ begin
353+ Parent:= Self;
354+ Height:= 75;
355+ Align:= alBottom;
356+ end;
357+
358+ VerticalSplitter:= TSplitter.Create(Self);
359+ with (VerticalSplitter) do
360+ begin
361+ Parent:= Self;
362+ Align:= alBottom;
363+ end;
364+
365+ HorizontalSplitter:= TSplitter.Create(Self);
366+ with (HorizontalSplitter) do
367+ begin
368+ Parent:= Self;
369+ align:= alLeft;
370+ end;
371+
372+ LeftPanel:= TPanel.Create(Self);
373+ with (LeftPanel) do
374+ begin
375+ Parent:= Self;
376+ Width:= 125;
377+ Align:= alLeft;
378+ end;
379+
380+ MainPanel:= TPanel.Create(Self);
381+ with (MainPanel) do
382+ begin
383+ Parent:= Self;
384+ Align:= alClient;
385+ Caption:= 'Привет';
386+ end;
387+end;
388+```
389+
390+``` pascal
391+var
392+ BottomPanel: TPanel;
393+ VerticalSplitter: TPairSplitter;
394+ LeftPanel: TPanel;
395+ HorizontalSplitter: TPairSplitter;
396+ MainPanel: TPanel;
397+
398+begin
399+ VerticalSplitter:= TPairSplitter.Create(Self);
400+ with (VerticalSplitter) do
401+ begin
402+ Parent:= Self;
403+ Align:= alClient;
404+ Width:= Self.Width;
405+ Height:= Self.Height;
406+ SplitterType:= pstVertical;
407+ Position:= Height - 75;
408+ Sides[0].Width:= Width;
409+ Sides[0].Height:= Position;
410+ end;
411+
412+ HorizontalSplitter:= TPairSplitter.Create(Self);
413+ with (HorizontalSplitter) do
414+ begin
415+ Parent:= VerticalSplitter.Sides[0];
416+ Width:= Self.Width;
417+ Height:= VerticalSplitter.Position;
418+ align:= alClient;
419+ SplitterType:= pstHorizontal;
420+ Position:= 125;
421+ end;
422+
423+ LeftPanel:= TPanel.Create(Self);
424+ with (LeftPanel) do
425+ begin
426+ Parent:= HorizontalSplitter.Sides[0];
427+ Align:= alClient;
428+ end;
429+
430+ MainPanel:= TPanel.Create(Self);
431+ with (MainPanel) do
432+ begin
433+ Parent:= HorizontalSplitter.Sides[1];
434+ Align:= alClient;
435+ Caption:= 'Привет';
436+ end;
437+
438+ BottomPanel:= TPanel.Create(Self);
439+ with (BottomPanel) do
440+ begin
441+ Parent:= VerticalSplitter.Sides[1];
442+ Align:= alClient;
443+ end;
444+end;
445+```
446+
448447Таким образом, как вы видите, \[преобразование\] справедливо для большей \[части кода\] с \[сохранением\] иерархии элементов управления. И если вы знакомы со \[структурой\] DFM-файлов, изменения, необходимые для преобразования DFM -\> LFM, должны быть очевидны из выше приведенного, поскольку они являются такими же изменениями в Parent/Owner и т.д.
449448
450449Таким образом, приведенный выше пример будет что-то вроде -
451450
452-<table>
453-<tbody>
454-<tr>
455-<td class="header"><p><strong>Delphi DFM</strong></p>
456-<div style="font-weight: normal">
457-<p><strong>(посторонние значения удалены)</strong></p></td>
458-<td class="header"><p><strong>Lazarus LFM</strong></p>
459-<div style="font-weight: normal">
460-<p><strong>(большинство свойств width, height... и т.д. удалены)</strong></p></td>
461-</tr>
462-<tr>
463-<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>
464-<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a> Height = <span class="dv">3</span></span>
465-<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> Cursor = crVSplit</span>
466-<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a> Align = alBottom</span>
467-<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">end</span></span>
468-<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="kw">object</span> HorizontalSplitter: TSplitter</span>
469-<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a> Width = <span class="dv">3</span></span>
470-<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a> Align = alLeft</span>
471-<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="kw">end</span></span>
472-<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="kw">object</span> BottomPanel: TPanel</span>
473-<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a> Height = <span class="dv">75</span></span>
474-<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a> Align = alBottom</span>
475-<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="kw">end</span></span>
476-<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="kw">object</span> LeftPanel: TPanel</span>
477-<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a> Width = <span class="dv">125</span></span>
478-<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a> Align = alLeft</span>
479-<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="kw">end</span></span>
480-<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a><span class="kw">object</span> MainPanel: TPanel</span>
481-<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a> Align = alClient</span>
482-<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a><span class="kw">end</span></span></code></pre></div></td>
483-<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>
484-<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a> Align = alClient</span>
485-<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> SplitterType = pstVertical</span>
486-<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> Position = <span class="dv">225</span></span>
487-<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a> Height = <span class="dv">300</span></span>
488-<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> Width = <span class="dv">400</span></span>
489-<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a> <span class="kw">object</span> Pairsplitterside1: TPairSplitterIde</span>
490-<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a> <span class="kw">object</span> HorizontalSplitter: TPairSplitter</span>
491-<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a> Align = alClient</span>
492-<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a> Position = <span class="dv">125</span></span>
493-<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a> <span class="kw">object</span> Pairsplitterside3: TPairSplitterIde</span>
494-<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a> Width = <span class="dv">125</span></span>
495-<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a> <span class="kw">object</span> LeftPanel: TPanel</span>
496-<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a> Align = alClient</span>
497-<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a> Width = <span class="dv">125</span></span>
498-<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
499-<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
500-<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a> <span class="kw">object</span> Pairsplitterside4: TPairSplitterIde</span>
501-<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a> <span class="kw">object</span> MainPanel: TPanel</span>
502-<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a> Align = alClient</span>
503-<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
504-<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
505-<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
506-<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
507-<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a> <span class="kw">object</span> Pairsplitterside2: TPairSplitterIde</span>
508-<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a> <span class="kw">object</span> BottomPanel: TPanel</span>
509-<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a> Align = alClient</span>
510-<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a> Height = <span class="dv">75</span></span>
511-<span id="cb2-29"><a href="#cb2-29" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
512-<span id="cb2-30"><a href="#cb2-30" aria-hidden="true" tabindex="-1"></a> <span class="kw">end</span></span>
513-<span id="cb2-31"><a href="#cb2-31" aria-hidden="true" tabindex="-1"></a><span class="kw">end</span></span></code></pre></div></td>
514-</tr>
515-</tbody>
516-</table>
451+**Delphi DFM**
452+
453+**(посторонние значения удалены)**
454+
455+**Lazarus LFM**
456+
457+**(большинство свойств width, height... и т.д. удалены)**
458+
459+``` pascal
460+object VerticalSplitter: TSplitter
461+ Height = 3
462+ Cursor = crVSplit
463+ Align = alBottom
464+end
465+object HorizontalSplitter: TSplitter
466+ Width = 3
467+ Align = alLeft
468+end
469+object BottomPanel: TPanel
470+ Height = 75
471+ Align = alBottom
472+end
473+object LeftPanel: TPanel
474+ Width = 125
475+ Align = alLeft
476+end
477+object MainPanel: TPanel
478+ Align = alClient
479+end
480+```
481+
482+``` pascal
483+object VerticalSplitter: TPairSplitter
484+ Align = alClient
485+ SplitterType = pstVertical
486+ Position = 225
487+ Height = 300
488+ Width = 400
489+ object Pairsplitterside1: TPairSplitterIde
490+ object HorizontalSplitter: TPairSplitter
491+ Align = alClient
492+ Position = 125
493+ object Pairsplitterside3: TPairSplitterIde
494+ Width = 125
495+ object LeftPanel: TPanel
496+ Align = alClient
497+ Width = 125
498+ end
499+ end
500+ object Pairsplitterside4: TPairSplitterIde
501+ object MainPanel: TPanel
502+ Align = alClient
503+ end
504+ end
505+ end
506+ end
507+ object Pairsplitterside2: TPairSplitterIde
508+ object BottomPanel: TPanel
509+ Align = alClient
510+ Height = 75
511+ end
512+ end
513+end
514+```
517515
518516### TCustomTreeView/TTreeView
519517
520518И VCL, и LCL предоставляют компонент TCustomTreeView/TTreeView, используемый для древовидных списков данных с несколькими узлами, расширенного выбора и списков изображений, и хотя фактические функции сопоставимы, не все свойства полностью совместимы. Основные различия заключаются в следующем -
521519
522520**Список не полон, но обновлен для включения в него функции TCustomTreeView Mark и protected-методов**
523521
5245221. LCL предоставляет TCustomTreeView.Options, набор опций, которые можно установить в элементе управления, чтобы изменить его поведение и внешний вид. Вот эти опции:
525523 - tvoAllowMultiselect - включает режим выбора нескольких узлов, эквивалентный включению TCustomTreeView.MultiSelect в VCL D6
526524 - tvoAutoExpand - автоматическое раскрытие узлов, что эквивалентно включению TCustomTreeView.AutoExpand
527525 - tvoAutoInsertMark - обновляет предосмотр Drag при перемещении мышью.
528526 - tvoAutoItemHeight - автоматически регулирует высоту элемента.
529527 - tvoHideSelection - не помечать выбранный элемент.
530528 - tvoHotTrack - использовать Hot Tracking, что эквивалетно включению TCustomTreeview.HotTrack
531529 - tvoKeepCollapsedNodes - сохранять дочерние узлы при их сжатии/сворачивании
532530 - tvoReadOnly - сделать Treeview доступным только для чтения, эквивалентно включению TCustomTreeview.ReadOnly
533531 - tvoRightClickSelect - разрешить использовать правую кнопку мыши для выбора узлов, что эквивалентно включению TCustomTreeView.RightClickSelect
534532 - tvoRowSelect - разрешить выбор строк, что эквивалентно включению TCustomTreeView.RowSelect
535533 - tvoShowButtons - показывать кнопки, что эквивалентно включению TCustomTreeView.ShowButtons
536534 - tvoShowLines - показывать линии узлов, что эквивалентные включению TCustomTreeView.ShowLines
537535 - tvoShowRoot - показывать корневые элементы, что эквивалентные включению TCustomTreeView.ShowRoot
538536 - tvoShowSeparators - показывать разделитель
539537 - tvoToolTips - показывать подсказки для отдельных узлов
5405382. LCL предоставляет дополнительные свойства:
541539 - Событие TCustomTreeView.OnSelectionChange
542540 - TCustomTreeView.DefaultItems, для количества элементов \[дерева\] по умолчанию
543541 - TCustomTreeView.ExpandSignType для определения знака, используемого в раскрывающихся/сворачивающихся узлах
5445423. Хотя большинство событий OnDrag/OnDock доступны в LCL, они не работают. Для получения дополнительной информации см. предыдущий раздел [[Lazarus For Delphi Users/ru|Control Dragging/Docking]].
545543
546544### Сообщения / События
547545
548546Порядок и частота сообщений и событий (OnShow, OnActivate, OnEnter, ...) отличаются от VCL и зависят от [[Widgetset|widgetset]]. LCL предоставляет подмножество WinAPI-подобных сообщений, чтобы упростить перенос компонентов Delphi, но почти все сообщения LCL работают несколько иначе, чем аналоги VCL/WinAPI. Большая часть кода Delphi, использующего сообщения WinAPI, использует их, потому что VCL не имеет функции или по соображениям скорости. Такие вещи редко работают одинаково в LCL, поэтому их нужно проверять вручную. Вот почему сообщения LCL называются, например, LM_SIZE вместо WM_SIZE (модуль Lmessages).
549547
550548**Замечание по обработке пользовательских сообщений!** Начиная с версии 0.9.26 (декабрь 2008г.), способ обработки пользовательских сообщений WinApi (например, WM_HOTKEY, WM_SYSCOMMAND) отличается от способа обработки этих сообщений в Delphi. В настоящее время вы не можете обработать их с помощью директивы **message** или переопределением метода *WndProc* формы. Единственный способ обработать их в форме - это самому перехватить сообщение Windows *windowproc*. Подробнее читайте здесь: [[Win32/64 Interface|Processing non-user messages in your window]]
551549
552550## См. также
553551
554552- [[Code Conversion Guide/ru|Code Conversion Guide (from Delphi &amp; Kylix)]]
555553- [[Compile With Delphi/ru|Compile With Delphi]]
556554
557555---
558556*From the Free Pascal wiki, page "Lazarus For Delphi Users/ru", as it stood on 2019-12-22 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