Sign in Join
Wiki copytemporary

Lazarus For Delphi Users/ru: what changed

Revision 2 to 3. 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
40-`unit1 in 'path/Unit1.pas';`
40+```text
41+unit1 in 'path/Unit1.pas';
42+```
4143
4244Такие пути со словом 'in' специфичны для Delphi, и не работают в Lazarus, поэтому не используйте их. Вместо этого в параметрах проекта (**Проект-\>Параметры проекта...**) на странице **Параметры компилятора-\>Пути** задайте пути к модулям, находящимся за пределами каталога проекта. Большинство путей к модулям задаются автоматически после добавления зависимости от какого-либо пакета. Например, во все стандартные проекты Lazarus LCL по умолчанию добавляется зависимость от пакета LCL, поэтому в каждом новом проекте Lazarus LCL (**Проект-\>Создать проект...-\>Приложение**) пути ко всем модулям LCL известны без вашего участия.
4345
4446Delphi хранит параметры компилятора в файле .dpr (например, {\$APPTYPE CONSOLE}). Lazarus игнорирует такую запись. Вместо этого используйте страницу **Параметры компилятора** в диалоге **Параметры проекта**.
4547
4648### Среда Lazarus не бывает "пустой"
4749
4850В среде Lazarus всегда открыт проект. Единственный способ "закрыть" проект - выход из Lazarus или открытие другого проекта. Это связано с тем, что проект Lazarus - ещё и "сеанс работы". Сведения о сеансе (например, параметры редактора) также хранятся в файле .lpi, и при повторном открытии проекта состояние редактора восстанавливается.
4951
5052**Пример.** Вы отлаживаете приложение и расставили несколько точек останова и закладок. Вы можете в любой момент сохранить проект, закрыть Lazarus или открыть другой проект. При повторном открытии проекта (даже на другом компьютере) все точки останова, закладки, открытые файлы, положение курсора, история переходов будут восстановлены.
5153
5254### Редактор исходного кода
5355
5456В меню Сервис -\> Параметры -\> Редактор -\> Комбинации клавиш могут быть заданы практически любые комбинации клавиш.
5557
5658Среда разработки Lazarus располагает множеством инструментов для работы с кодом. Многие из них выглядят и работают так же, как и в Delphi. Но есть одно важное отличие: Lazarus не использует компилятор для получения сведений о коде, а работает с ним напрямую. Это даёт ряд важных преимуществ:
5759
5860Редактор работает с "комментариями". В Delphi комментарии это просто место между фрагментами кода. Здесь не действуют никакие средства работы с кодом, и комментарии смещаются при автоматической вставке нового кода. В Lazarus можно найти объявление даже в закоментированном коде. Это не очень надёжно, однако работает в большинстве случаев. При вставке нового кода среда разработки использует некоторую эвристику, чтобы сохранить комментарий и код вместе. К примеру, строка `"c: char; // comment"` разделяться не будет.
5961
6062Дельфийское «Автозавершение кода» (`Ctrl` + `Space`) в Lazarus называется «Автозавершение идентификатора». Термин Lazarus'овское «Автозавершение кода» - это функция, объединяющая «Автоматическое завершение класса» (как в Delphi), «Автозавершение локальной переменной» и «Автозавершение назначения события». Все они вызываются по `Ctrl` + `Space` + `C`, что подразумевает, что среда IDE определяет положение курсора.
6163
6264#### Пример для автозавершения локальной переменной
6365
6466Предположим, вы только что создали новый метод и написали оператор "i:=3;"
6567
6668``` pascal
6769procedure TForm1.DoSomething;
6870begin
6971 i := 3;
7072end;
7173```
7274
7375Наведите курсор на идентификатор «i» и нажмите `Ctrl`+`Shift`+`C`, чтобы получить:
7476
7577``` pascal
7678procedure TForm1.DoSomething;
7779var i: Integer;
7880begin
7981 i := 3;
8082end;
8183```
8284
8385#### Пример автозавершения назначения события
8486
8587Приятной особенностью инспектора объектов является автоматическое создание методов. Заодно, вы можете получить редактор исходного кода для создания событий.\
8688Например:
8789
8890``` pascal
8991Button1.OnClick:=
9092```
9193
9294Поместите курсор за оператором присваивания ":=" и нажмите `Ctrl`+`Shift`+`C`.
9395
9496------------------------------------------------------------------------
9597
9698Прим.перев.: при этом сформированный код будет выглядеть так:
9799
98100``` pascal
99101procedure TForm1.FormCreate(Sender: TObject);
100102begin
101103 Button1.OnClick:=@Button1Click;
102104end;
103105
104106procedure TForm1.Button1Click(Sender: TObject);
105107begin
106108
107109end;
108110```
109111
110112#### Пример автозавершения вызова процедуры
111113
112114Предположим, вы только что написали оператор "DoSomething(Width);"
113115
114116``` pascal
115117procedure SomeProcedure;
116118var
117119 Width: integer;
118120begin
119121 Width:=3;
120122 DoSomething(Width);
121123end;
122124```
123125
124126Наведите курсор на идентификатор «DoSomething» и нажмите `Ctrl`+`Shift`+`C`, чтобы получить:
125127
126128``` pascal
127129procedure DoSomething(aWidth: LongInt);
128130begin
129131
130132end;
131133
132134procedure SomeProcedure;
133135var
134136 Width: integer;
135137begin
136138 Width:=3;
137139 DoSomething(Width);
138140end;
139141```
140142
141143#### "Автозавершение слова" Ctrl+W
142144
143145Он работает аналогично «Автозавершению идентификатора», но работает не для идентификаторов паскалей, а для всех слов. Позволяет выбрать все слова во всех открытых файлах, начиная с одинаковых букв.
144146
145147#### Поддержка Include-файлов
146148
147149Delphi не поддерживал их, поэтому вы, вероятно, еще не создавали много включаемых файлов. Но у включаемых файлов есть большое преимущество: они позволяют писать (не)зависимый от платформы код, не запутывая ваш код IFDEF'ами. Например: переход по методу, автозавершение класса, объявление find, ... все работает с include-файлами.
148150
149151Есть много вариантов функций кода.
150152
151153### Designer
152154
153155\- см. руководство пользователя
154156
155157#### Инспектор объектов
156158
157159В IDE Delphi и IDE Lazarus'а Инспектор объектов используется для редактирования свойств компонента, назначения событий и т.д. Ниже приведены некоторые незначительные отличия, которые следует отметить при использовании:
158160
1591611. Начиная с Delphi 5, существует Дерево Объектов(Object Treeview), которое можно использовать для навигации и выбора объектов в соответствии с иерархией в дополнение к традиционному выпадающему списку в Инспекторе объектов. В Lazarus это является частью Инспектора объектов и используется вместо раскрывающегося списка по умолчанию, вы можете выбрать его из контекстного меню "Show Component Tree"(Показать дерево компонентов), чтобы использовать/не использовать.
1601622. В Delphi двойной щелчок на пустом событии автоматически создаст его и откроет редактор исходного кода в этой позиции, в Lazarus справа от выбранного выпадающего меню есть кнопка, которая выполняет это действие.
1611633. В Delphi вы должны вручную удалить имя события в редакторе, чтобы удалить привязку к нему, в Lazarus вы можете нажать на раскрывающийся список и выбрать "(None)"(Нет).
1621644. Двойной щелчок по обычным свойствам, таким как логическое значение, не изменит его значение (как это произошло бы случае с Events(Событием)), вы должны выбрать его из выпадающего списка. А чтобы открыть их с прилагаемой формой редактора, вы должны нажать кнопку «...» справа от раскрывающегося меню.
163165
164166#### Пакеты
165167
166168- Может ли Lazarus установить и использовать пакеты Delphi?
167169
168170
169171Нет, потому что они требуют магии компилятора Delphi.
170172
171173- Должны ли они быть специально сделанными для Lazarus?
172174
173175
174176Да.
175177
176178Создайте новый пакет, сохраните его в каталоге с исходниками пакета (обычно это тот же каталог файла .dpk), добавьте LCL как требуемый пакет и, наконец, добавьте файлы .pas. Теперь вы можете установить его или использовать в своих проектах. Есть некоторые [[packages|различия между пакетами Lazarus и Delphi]].
177179
178180## VCL -\> LCL
179181
180182Хотя VCL и LCL служат большей части одной и той же цели - объектно-ориентированной иерархии компонентов, особенно ориентированной на быструю разработку приложений, они не идентичны. Например, в то время как VCL предоставляет много невизуальных компонентов, LCL пытается предоставлять только визуальные, в то время как большинство невизуальных компонентов (таких как доступ к базе данных) предоставляются с FCL, включенным в [[Free Pascal]].
181183
182184Кроме того, многие элементы управления, которые представлены в VCL, могут отсутствовать в LCL, или наоборот, или даже если элементы управления существуют в обоих, они не являются клонами, и при переносе необходимо внести изменения в приложения, компоненты и элементы управления.
183185
184186Ниже приведена попытка для пользователя Delphi дать достаточно полное описание основных различий или несовместимостей между ними. Она охватывает различия в первую очередь особенно для VCL D4, хотя иногда также D5, D6 или D7; и с текущим LCL, как в CVS. Таким образом, оно может не всегда соответствовать версии Delphi, к которой вы привыкли, или полностью соответствовать текущему LCL, который у вас есть. Если вы видите неточности между нижеследующим и LCL, как в CVS, или ваш Delphi не стесняется добавлять и изменять, чтобы сделать его максимально полным для всех людей.
185187
186188### TControl.Font/TControl.ParentFont
187189
188190В VCL довольно распространено и нормально использовать определенное имя шрифта и свойства шрифта, такие как жирный шрифт и курсив для элементов управления, и ожидать, что это значение всегда будет соблюдаться. Далее предоставляется свойство TControl.ParentFont, которое гарантирует, что элемент управления всегда будет следовать за шрифтом его родителя. Опять же подразумеваемое предположение, что эти значения будут всегда соблюдаться, даже независимо от настроек внешнего вида Windows.
189191
190192Это не всегда верно в LCL, да и не может быть. LCL, являющийся кросс-платформой/кросс-интерфейсом по своей природе, предпочитает сбалансированный подход и вместо этого всегда будет пытаться использовать собственные настройки Рабочего стола/Внешнего вида инструментария или Темы для любых виджетов. Например, если используется интерфейс GTK, а тема gtk предоставляет определенный шрифт для кнопок, то кнопки LCL всегда будут пытаться использовать этот шрифт.
191193
192194Это означает, что большинство элементов управления LCL не имеют того же уровня управления проектированием, который часто ожидается в VCL, скорее, только те пользовательские элементы управления, которые нарисованы Canvas вместо назначенного интерфейса, могут постоянно изменяться таким образом независимо от используемого интерфейса.
193195
194196### Control Dragging/Docking
195197
196198В VCL большинство (Win)Controls реализуют методы и функции обратного вызова для обработки перетаскивания и закрепления элементов управления, например, перетаскивая элемент управления с одной панели и закрепляя его на другой панели во время выполнения.
197199
198200Эта функциональность в настоящее время не реализована/не завершена в LCL, хотя в настоящее время она находится на начальных этапах планирования и должна в конечном итоге поддерживать некоторый уровень совместимости для этого типа поведения, если не точно таким же образом.
199201
200202В настоящее время это означает, что ни один элемент управления не будет наследовать/использовать следующие функции, процедуры, свойства или события TControl:
201203
202204``` pascal
203205Protected
204206 function GetDockEdge(MousePos: TPoint): TAlign;
205207 function GetDragImages: TDragImageList;
206208 function GetFloating: Boolean;
207209 function GetFloatingDockSiteClass: TWinControlClass;
208210 procedure DoEndDrag(Target:TObject); X, Y: Integer);
209211 procedure DockTrackNoTarget(Source: TDragDockObject; X, Y: Integer);
210212 procedure DoEndDock(Target: TObject; X, Y: Integer);
211213 procedure DoDock(NewDockSite: TWinControl; var ARect: TRect);
212214 procedure DoStartDock(var DragObject: TDragObject);
213215 procedure DragCanceled;
214216 procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState;
215217 var Accept: Boolean);
216218 procedure DoEndDrag(Target: TObject; X, Y: Integer);
217219 procedure DoStartDrag(var DragObject: TDragObject);
218220 procedure DrawDragDockImage(DragDockObject: TDragDockObject);
219221 procedure EraseDragDockImage(DragDockObject: TDragDockObject);
220222 procedure PositionDockRect(DragDockObject: TDragDockObject);
221223 procedure SetDragMode(Value: TDragMode);
222224 property DragKind: TDragKind;
223225 property DragCursor: TCursor;
224226 property DragMode: TDragMode;
225227 property OnDragDrop: TDragDropEvent;
226228 property OnDragOver: TDragOverEvent;
227229 property OnEndDock: TEndDragEvent;
228230 property OnEndDrag: TEndDragEvent;
229231 property OnStartDock: TStartDockEvent;
230232 property OnStartDrag: TStartDragEvent;
231233public
232234 function Dragging: Boolean;
233235 function ManualDock(NewDockSite: TWinControl; DropControl: TControl;
234236 ControlSide: TAlign): Boolean;
235237 function ManualFloat(ScreenPos: TRect): Boolean;
236238 function ReplaceDockedControl(Control: TControl; NewDockSite: TWinControl;
237239 DropControl: TControl; ControlSide: TAlign): Boolean;
238240 procedure BeginDrag(Immediate: Boolean; Threshold: Integer);
239241 procedure Dock(NewDockSite: TWinControl; ARect: TRect);
240242 procedure DragDrop(Source: TObject; X, Y: Integer);
241243 procedure EndDrag(Drop: Boolean);
242244 property DockOrientation: TDockOrientation;
243245 property Floating: Boolean;
244246 property FloatingDockSiteClass: TWinControlClass;
245247 property HostDockSite: TWinControl;
246248 property LRDockWidth: Integer;
247249 property TBDockHeight: Integer;
248250 property UndockHeight: Integer;
249251 property UndockWidth: Integer;
250252```
251253
252254Вот эти классы не существуют/непригодны для использования -
253255
254256``` pascal
255257TDragImageList = class(TCustomImageList)
256258TDockZone = class
257259TDockTree = class(TInterfacedObject, IDockManager)
258260TDragObject = class(TObject)
259261TBaseDragControlObject = class(TDragObject)
260262TDragControlObject = class(TBaseDragControlObject)
261263TDragDockObject = class(TBaseDragControlObject)
262264```
263265
264266а вот эти функции также непригодны / несовместимы -
265267
266268``` pascal
267269function FindDragTarget(const Pos: TPoint;
268270 AllowDisabled: Boolean) : TControl;
269271procedure CancelDrag;
270272function IsDragObject(sender: TObject): Boolean;
271273```
272274
273275Запуск менеджера пристыковки окон описан здесь: [[Anchor Docking]]
274276
275277### TEdit/TCustomEdit
276278
277279Элементы управления Edit, хотя они и функционируют в основном как в LCL, так и в VCL, имеют некоторые особенности, которые необходимо учитывать при преобразовании:
278280
2792811. Из-за ограничений в интерфейсах TEdit.PasswordChar работает пока не во всех интерфейсах (хотя со временем может и будет), вместо этого следует использовать TCustomEdit.EchoMode emPassword в том случае, если текст события должен быть скрыт.
2802822. Событие Drag/Dock еще не реализовано. Для получения дополнительной информации см. предыдущий раздел Control Dragging/Docking.
2812833. Свойства шрифта обычно игнорируются для согласованности интерфейса, для подробного объяснения, что и как, пожалуйста, см. TControl.Font/TControl.ParentFont
282284
283285### TDBImage
284286
285287Delphi и Lazarus имеют элемент управления [[TDBImage]], который показывает изображения, хранящиеся в поле базы данных. В текущих стабильных версиях (1.2.4) Lazarus хранит информацию о типе изображения в поле базы данных перед фактическими данными изображения. См. процедуру *TDBImage.UpdateData*. Это означает, что Delphi и более старые реализации Lazarus не совместимы.
286288
287289В текущей стабильной версии Lazarus (1.2.0+) реализованы изменения, позволяющие использовать поведение, совместимое с Delphi. Пожалуйста, см. [[Lazarus 1.2.0 release notes|Lazarus_1.2.0_release_notes#TDBImage]] для получения подробной информации о том, как активировать это.
288290
289291Текущий транк Lazarus'а возвращается к Delphi-совместимому поведению при чтении полей базы данных в формате Delphi в TDBImage.
290292
291293### (необязательно) TSplitter -\> TPairSplitter
292294
293295**Пожалуйста, улучшите меня!**
294296
295297Теперь в LCL есть элемент управления [[TSplitter/ru|TSplitter]], поэтому нет необходимости его преобразовывать.
296298
297299Тем не менее, если вы хотите, здесь приводится объяснение:
298300
299301Следующее в основном основано на вопросах пользователя Vincent Snijders в списках рассылки и ответов [Andrew Johnson](http://lazarus-ccr.sourceforge.net/index.php?wiki=AndrewJohnson):
300302
301303В VCL элементы управления "Splitting" - это ползунок, который можно перетаскивать между двумя компонентами для предоставления большего или меньшего пространства одному из них за счет другого; выполняется \[посредством компонента\] TSplitter. Например, в IDE Delphi его можно увидеть между закрепленным Code Explorer и Source Viewer.
302304
303305LCL предоставляет свой собственный элемент управления, называемый [[TPairSplitter/ru|TPairSplitter]], который служит для тех же целей, однако он не совместим с Delphi, поэтому в случае переноса кода потребуется исправление "поврежденного" кода VCL или DFM-файлов Delphi, даже если используется много общего между двумя этими компонентами.
304306
305307Так в чем именно различия?
306308
307309Ну, самые большие различия в том, что VCL TSplitter не имеет \[размещенных на нем\] дочерних элементов, вместо этого он помещается между двумя правильно выровненными элементами управления и позволяет изменять их размер во время выполнения независимо от его собственного размера. На каждой стороне должно быть два элемента управления, чтобы что-нибудь сделать. Простым примером будет форма с выровненной по левому краю панелью, выровненным по левому краю разделителем и второй выровненной по клиенту панелью. Во время выполнения вы можете затем изменить размер, заданный для каждой панели, перетаскивая за специальный ползунок, предоставляемый элементом управления Splitter.
308310
309311Однако с точки зрения LCL, TPairSplitter - это особый вид управления с двумя панелями, и он может быть полезен только в том случае, если элементы управления для разделения находятся на этих панелях, но он все равно будет выполнять разбиение между этими панелями, независимо от того, что расположено на них. Таким образом, по аналогии с предыдущим примером, вы получите форму с выровненным клиентом TPairSplitter, выровненным по панели клиентом с левой стороны и выровненным по панели клиентом с правой стороны.
310312
311313------------------------------------------------------------------------
312314
313315Прим.перев.: иными словами, TPairSplitter - это готовый контейнер, разделенный TSplitter на две половины (в зависимости от значения свойства SplitterType на левую/правую или верхнюю/нижнюю), каждая из которых уже имеет привязку alClient, готова принимать на себя дочерние элементы и меняет свои размеры при перемещении ползунка разделителя.
314316
315317------------------------------------------------------------------------
316318
317319Другое важное отличие состоит в том, что в VCl, поскольку TSplitter является собственным TControl, положение сохраняется относительно других элементов управления при изменении размера. Поэтому, например, клиентская панель будет расти, в то время как другие панели этого делать не будут, таким образом, позиция разделения является относительна к выравниванию разделяемых элементов управления.
318320
319321В LCL, поскольку боковые панели отделены друг от друга, у TPairSplitter есть свойство Position, которое является абсолютным по отношению к верхнему или левому краям \[родительского элемента\]. Поэтому при изменении размера фактическая позиция не изменяется в зависимости от содержимого, отсюда, необходимо установить обратный вызов, чтобы обеспечить сохранение соотношения при изменении размера, если это важно.
320322
321323------------------------------------------------------------------------
322324
323325Прим.перев.: проще говоря, Position - это позиция ползунка TPairSplitter относительно левого/верхнего края контейнера (в зависимости от значения SplitterType = pstHorizontal/pstVertical соответственно).
324326
325327------------------------------------------------------------------------
326328
327329Например, если правая сторона вертикального разбиения должна иметь поведение, аналогичное alClient, необходимо добавить обратный вызов изменения размера формы, который выполняет что-то вроде:
328330
329331``` pascal
330332 PairSplitter.Position := PairSplitter.Width - PairSplitter.Position;
331333```
332334
333335Итак, как я могу преобразовать существующий код, использующий TSplitter, в TPairSplitter?
334336
335337Если разделитель и элементы управления создаются внутри фактической функции (например, при создании формы), преобразование не должно быть слишком сложным, в первую очередь реорганизуйте код, чтобы создать элементы управления в порядке новой иерархии, и установите родительские элементы дочерних элементов управления для разделения на левую/верхнюю и правую/нижнюю части PairSplitter. Пример изменений:
336338
337339**VCL**
338340
339341**LCL**
340342
341343``` pascal
342344var
343345 BottomPanel: TPanel;
344346 VerticalSplitter: TSplitter;
345347 LeftPanel: TPanel;
346348 HorizontalSplitter: TSplitter;
347349 MainPanel: TPanel;
348350
349351begin
350352 BottomPanel:= TPanel.Create(Self);
351353 with (BottomPanel) do
352354 begin
353355 Parent:= Self;
354356 Height:= 75;
355357 Align:= alBottom;
356358 end;
357359
358360 VerticalSplitter:= TSplitter.Create(Self);
359361 with (VerticalSplitter) do
360362 begin
361363 Parent:= Self;
362364 Align:= alBottom;
363365 end;
364366
365367 HorizontalSplitter:= TSplitter.Create(Self);
366368 with (HorizontalSplitter) do
367369 begin
368370 Parent:= Self;
369371 align:= alLeft;
370372 end;
371373
372374 LeftPanel:= TPanel.Create(Self);
373375 with (LeftPanel) do
374376 begin
375377 Parent:= Self;
376378 Width:= 125;
377379 Align:= alLeft;
378380 end;
379381
380382 MainPanel:= TPanel.Create(Self);
381383 with (MainPanel) do
382384 begin
383385 Parent:= Self;
384386 Align:= alClient;
385387 Caption:= 'Привет';
386388 end;
387389end;
388390```
389391
390392``` pascal
391393var
392394 BottomPanel: TPanel;
393395 VerticalSplitter: TPairSplitter;
394396 LeftPanel: TPanel;
395397 HorizontalSplitter: TPairSplitter;
396398 MainPanel: TPanel;
397399
398400begin
399401 VerticalSplitter:= TPairSplitter.Create(Self);
400402 with (VerticalSplitter) do
401403 begin
402404 Parent:= Self;
403405 Align:= alClient;
404406 Width:= Self.Width;
405407 Height:= Self.Height;
406408 SplitterType:= pstVertical;
407409 Position:= Height - 75;
408410 Sides[0].Width:= Width;
409411 Sides[0].Height:= Position;
410412 end;
411413
412414 HorizontalSplitter:= TPairSplitter.Create(Self);
413415 with (HorizontalSplitter) do
414416 begin
415417 Parent:= VerticalSplitter.Sides[0];
416418 Width:= Self.Width;
417419 Height:= VerticalSplitter.Position;
418420 align:= alClient;
419421 SplitterType:= pstHorizontal;
420422 Position:= 125;
421423 end;
422424
423425 LeftPanel:= TPanel.Create(Self);
424426 with (LeftPanel) do
425427 begin
426428 Parent:= HorizontalSplitter.Sides[0];
427429 Align:= alClient;
428430 end;
429431
430432 MainPanel:= TPanel.Create(Self);
431433 with (MainPanel) do
432434 begin
433435 Parent:= HorizontalSplitter.Sides[1];
434436 Align:= alClient;
435437 Caption:= 'Привет';
436438 end;
437439
438440 BottomPanel:= TPanel.Create(Self);
439441 with (BottomPanel) do
440442 begin
441443 Parent:= VerticalSplitter.Sides[1];
442444 Align:= alClient;
443445 end;
444446end;
445447```
446448
447449Таким образом, как вы видите, \[преобразование\] справедливо для большей \[части кода\] с \[сохранением\] иерархии элементов управления. И если вы знакомы со \[структурой\] DFM-файлов, изменения, необходимые для преобразования DFM -\> LFM, должны быть очевидны из выше приведенного, поскольку они являются такими же изменениями в Parent/Owner и т.д.
448450
449451Таким образом, приведенный выше пример будет что-то вроде -
450452
451453**Delphi DFM**
452454
453455**(посторонние значения удалены)**
454456
455457**Lazarus LFM**
456458
457459**(большинство свойств width, height... и т.д. удалены)**
458460
459-``` pascal
461+``` lfm
460462object VerticalSplitter: TSplitter
461463 Height = 3
462464 Cursor = crVSplit
463465 Align = alBottom
464466end
465467object HorizontalSplitter: TSplitter
466468 Width = 3
467469 Align = alLeft
468470end
469471object BottomPanel: TPanel
470472 Height = 75
471473 Align = alBottom
472474end
473475object LeftPanel: TPanel
474476 Width = 125
475477 Align = alLeft
476478end
477479object MainPanel: TPanel
478480 Align = alClient
479481end
480482```
481483
482-``` pascal
484+``` lfm
483485object VerticalSplitter: TPairSplitter
484486 Align = alClient
485487 SplitterType = pstVertical
486488 Position = 225
487489 Height = 300
488490 Width = 400
489491 object Pairsplitterside1: TPairSplitterIde
490492 object HorizontalSplitter: TPairSplitter
491493 Align = alClient
492494 Position = 125
493495 object Pairsplitterside3: TPairSplitterIde
494496 Width = 125
495497 object LeftPanel: TPanel
496498 Align = alClient
497499 Width = 125
498500 end
499501 end
500502 object Pairsplitterside4: TPairSplitterIde
501503 object MainPanel: TPanel
502504 Align = alClient
503505 end
504506 end
505507 end
506508 end
507509 object Pairsplitterside2: TPairSplitterIde
508510 object BottomPanel: TPanel
509511 Align = alClient
510512 Height = 75
511513 end
512514 end
513515end
514516```
515517
516518### TCustomTreeView/TTreeView
517519
518520И VCL, и LCL предоставляют компонент TCustomTreeView/TTreeView, используемый для древовидных списков данных с несколькими узлами, расширенного выбора и списков изображений, и хотя фактические функции сопоставимы, не все свойства полностью совместимы. Основные различия заключаются в следующем -
519521
520522**Список не полон, но обновлен для включения в него функции TCustomTreeView Mark и protected-методов**
521523
5225241. LCL предоставляет TCustomTreeView.Options, набор опций, которые можно установить в элементе управления, чтобы изменить его поведение и внешний вид. Вот эти опции:
523525 - tvoAllowMultiselect - включает режим выбора нескольких узлов, эквивалентный включению TCustomTreeView.MultiSelect в VCL D6
524526 - tvoAutoExpand - автоматическое раскрытие узлов, что эквивалентно включению TCustomTreeView.AutoExpand
525527 - tvoAutoInsertMark - обновляет предосмотр Drag при перемещении мышью.
526528 - tvoAutoItemHeight - автоматически регулирует высоту элемента.
527529 - tvoHideSelection - не помечать выбранный элемент.
528530 - tvoHotTrack - использовать Hot Tracking, что эквивалетно включению TCustomTreeview.HotTrack
529531 - tvoKeepCollapsedNodes - сохранять дочерние узлы при их сжатии/сворачивании
530532 - tvoReadOnly - сделать Treeview доступным только для чтения, эквивалентно включению TCustomTreeview.ReadOnly
531533 - tvoRightClickSelect - разрешить использовать правую кнопку мыши для выбора узлов, что эквивалентно включению TCustomTreeView.RightClickSelect
532534 - tvoRowSelect - разрешить выбор строк, что эквивалентно включению TCustomTreeView.RowSelect
533535 - tvoShowButtons - показывать кнопки, что эквивалентно включению TCustomTreeView.ShowButtons
534536 - tvoShowLines - показывать линии узлов, что эквивалентные включению TCustomTreeView.ShowLines
535537 - tvoShowRoot - показывать корневые элементы, что эквивалентные включению TCustomTreeView.ShowRoot
536538 - tvoShowSeparators - показывать разделитель
537539 - tvoToolTips - показывать подсказки для отдельных узлов
5385402. LCL предоставляет дополнительные свойства:
539541 - Событие TCustomTreeView.OnSelectionChange
540542 - TCustomTreeView.DefaultItems, для количества элементов \[дерева\] по умолчанию
541543 - TCustomTreeView.ExpandSignType для определения знака, используемого в раскрывающихся/сворачивающихся узлах
5425443. Хотя большинство событий OnDrag/OnDock доступны в LCL, они не работают. Для получения дополнительной информации см. предыдущий раздел [[Lazarus For Delphi Users/ru|Control Dragging/Docking]].
543545
544546### Сообщения / События
545547
546548Порядок и частота сообщений и событий (OnShow, OnActivate, OnEnter, ...) отличаются от VCL и зависят от [[Widgetset|widgetset]]. LCL предоставляет подмножество WinAPI-подобных сообщений, чтобы упростить перенос компонентов Delphi, но почти все сообщения LCL работают несколько иначе, чем аналоги VCL/WinAPI. Большая часть кода Delphi, использующего сообщения WinAPI, использует их, потому что VCL не имеет функции или по соображениям скорости. Такие вещи редко работают одинаково в LCL, поэтому их нужно проверять вручную. Вот почему сообщения LCL называются, например, LM_SIZE вместо WM_SIZE (модуль Lmessages).
547549
548550**Замечание по обработке пользовательских сообщений!** Начиная с версии 0.9.26 (декабрь 2008г.), способ обработки пользовательских сообщений WinApi (например, WM_HOTKEY, WM_SYSCOMMAND) отличается от способа обработки этих сообщений в Delphi. В настоящее время вы не можете обработать их с помощью директивы **message** или переопределением метода *WndProc* формы. Единственный способ обработать их в форме - это самому перехватить сообщение Windows *windowproc*. Подробнее читайте здесь: [[Win32/64 Interface|Processing non-user messages in your window]]
549551
550552## См. также
551553
552554- [[Code Conversion Guide/ru|Code Conversion Guide (from Delphi & Kylix)]]
553555- [[Compile With Delphi/ru|Compile With Delphi]]
554556
555557---
556558*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