Sign in Join
Wiki copytemporary

Extending the IDE/ru: what changed

Revision 3 to 4. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11# Расширение IDE
22
33## Обзор
44
55Lazarus IDE поддерживает несколько типов плагинов:
66
77Компоненты
88это элементы, найденные в палитре компонентов. Например, TButton (находится на странице Standard) можно использовать для создания кнопок.
99
1010Редакторы компонентов
1111при двойном щелчке по компоненту в Дизайнере вызывается редактор компонентов. Редактор компонента также может добавить дополнительный элемент во всплывающее меню Дизайнера (доступ к нему осуществляется по щелчку правой кнопкой мыши на компоненте в конструкторе).
1212
1313Редакторы свойств
1414Каждая строка в разделе сетки Инспектора объектов использует редактор свойств, чтобы разрешить установку или изменение значения этого свойства.
1515
1616Эксперты
1717Эксперты охватывают все другие типы плагинов. Они могут регистрировать новые пункты меню, регистрировать ярлыки или расширять другие функции IDE.
1818
1919Есть два возможных способа добавить свои собственные плагины в IDE Lazarus:
2020
21211. Напишите пакет, установите его и зарегистрируйте ваши плагины в процедуре 'Register' модуля.
22222. Расширьте код Lazarus и отправьте свой svn diff в список рассылки Lazarus.
2323
2424## Пакеты и зависимости Makefile
2525
2626Следующие шаги необходимы, если добавляются новые зависимости пакета.
2727
2828- Создание/Обновление Makefile для пакета через Package editor / More ... / Create Makefile.
2929- Исправление всех зависимостей. См. tools/updatemakefiles.lpi
3030
3131# Пункты меню
3232
3333Вы можете добавлять новые пункты меню, скрывать или перемещать существующие и добавлять подменю, разделы. Для ваших собственных форм вы можете зарегистрировать TMainMenu/TPopupMenu, чтобы другие пакеты могли расширять вашу форму дальше. Модуль **MenuIntf** пакета IDEIntf содержит всю регистрацию для меню и множество стандартных пунктов меню самой IDE.
3434
3535## Добавление пункта меню
3636
3737Одиночный элемент меню, такой как \[, например,\] 'View Object Inspector', называется **TIDEMenuCommand**. Вы можете создать его с помощью **RegisterIDEMenuCommand**, который имеет две формы с большим количеством параметров:
3838
3939``` pascal
4040function RegisterIDEMenuCommand(Parent: TIDEMenuSection;
4141 const Name, Caption: string;
4242 const OnClickMethod: TNotifyEvent = nil;
4343 const OnClickProc: TNotifyProcedure = nil;
4444 const Command: TIDECommand = nil;
4545 const ResourceName: String = ''
4646 ): TIDEMenuCommand; overload;
4747function RegisterIDEMenuCommand(const Path, Name, Caption: string;
4848 const OnClickMethod: TNotifyEvent = nil;
4949 const OnClickProc: TNotifyProcedure = nil;
5050 const Command: TIDECommand = nil;
5151 const ResourceName: String = ''
5252 ): TIDEMenuCommand; overload;
5353```
5454
5555Разница между этими двумя \[функциями\] только в том, как вы указываете родительский раздел меню. Вы можете указать раздел меню прямо или косвенно через путь. Многие стандартные разделы можно найти в модуле *MenuIntf*. Например, раздел **mnuTools**, который является \[пунктом\] меню *Tools* главной панели IDE. Он содержит раздел **itmSecondaryTools**, рекомендуемый для сторонних инструментов.
5656
5757Следующий \[код\] регистрирует новую команду меню с именем 'MyTool', с заголовком 'Start my tool' и при нажатии выполняет процедуру *StartMyTool*:
5858
5959``` pascal
6060procedure StartMyTool;
6161begin
6262 ... выполняется при нажатии на пункт меню ...
6363end;
6464
6565procedure Register;
6666begin
6767 RegisterIDEMenuCommand(itmSecondaryTools, 'MyTool','Start my tool',nil,@StartMyTool);
6868end;
6969```
7070
7171Если вы хотите вызвать метод вместо процедуры, используйте параметр **OnClickMethod**.
7272
7373Этот пункт меню не имеет сочетания клавиш. Если вы хотите \[назначить ему\] сочетание клавиш, вы должны создать **TIDECommand** и передать его в параметре **Command**. Например:
7474
7575``` pascal
7676uses ... IDECommands, MenuIntf;
7777...
7878var
7979 Key: TIDEShortCut;
8080 Cat: TIDECommandCategory;
8181 CmdMyTool: TIDECommand;
8282begin
8383 // регистрация сочетаний клавиш IDE и пункта меню
8484 Key := IDEShortCut(VK_UNKNOWN,[],VK_UNKNOWN,[]);
8585 Cat:=IDECommandList.FindCategoryByName(CommandCategoryToolMenuName);
8686 CmdMyTool := RegisterIDECommand(Cat,'Start my tool', 'Starts my tool to do some stuff', Key, nil, @StartMyTool);
8787 RegisterIDEMenuCommand(itmSecondaryTools, 'MyTool', 'Start my tool', nil, nil, CmdMyTool);
8888end;
8989```
9090
9191# Сочетания клавиш
9292
9393Все сочетания клавиш (ключи, которые вызывают какое-либо действие) зарегистрированы в IDECommandList. Вот пример того, как найти все команды, которые реагируют на клавиши `Ctrl`+`D` или две комбинации клавиш, начинающиеся с `Ctrl`+`D`:
9494
9595``` pascal
9696uses
9797 Classes, SysUtils, LCLProc, IDECommands;
9898
9999procedure ListCtrlD;
100100// список всех команд IDE с комбинациями клавиш <Ctrl>+<D>
101101var
102102 i: integer;
103103 Cmd: TIDECommand;
104104 Commands: TFPList;
105105begin
106106 Commands:=IDECommandList.FindCommandsByShortCut(IDEShortCut(VK_D,[],VK_UNKNOWN,[]));
107107 try
108108 for i:=0 to Commands.Count-1 do begin
109109 Cmd:=TIDECommand(Commands[i]);
110110 writeln('Cmd: ',Cmd.Name,
111111 ' A=',dbgs(Cmd.ShortcutA.Shift1),'-',Cmd.ShortcutA.Key1,
112112 ',',dbgs(Cmd.ShortcutA.Shift2),'-',Cmd.ShortcutA.Key2,
113113 ' B=',dbgs(Cmd.ShortcutB.Shift1),'-',Cmd.ShortcutB.Key1,
114114 ',',dbgs(Cmd.ShortcutB.Shift2),'-',Cmd.ShortcutB.Key2
115115 );
116116 end;
117117 finally
118118 Commands.Free;
119119 end;
120120end;
121121```
122122
123123# Конфигурационные файлы
124124
125125## Загрузка/Сохранение настроек
126126
127127Все конфигурационные файлы IDE хранятся в одном каталоге в виде XML-файлов. Пакеты также могут добавлять свои собственные файлы туда. Каталог [[pcp|primary config path]] можно прочитать с помощью:
128128
129129``` pascal
130130uses LazIDEIntf;
131131...
132132 Directory := LazarusIDE.GetPrimaryConfigPath;
133133```
134134
135135Пакеты могут создавать свои собственные файлы XML с помощью:
136136
137137``` pascal
138138uses
139139 ..., LCLProc, BaseIDEIntf, LazConfigStorage;
140140
141141const
142142 Version = 1;
143143var
144144 Config: TConfigStorage;
145145 SomeValue: String;
146146 SomeInteger: Integer;
147147 SomeBoolean: Boolean;
148148 FileVersion: LongInt;
149149begin
150150 SomeValue:='Default';
151151 SomeInteger:=3;
152152 SomeBoolean:=true;
153153
154154 // сохранение настроек
155155 try
156156 Config:=GetIDEConfigStorage('mysettings.xml',false);
157157 try
158158 // сохраняем номер версии, чтобы будущие расширения могли обрабатывать старые файлы конфигурации
159159 Config.SetDeleteValue('Path/To/The/Version',Version,0);
160160 // сохраняем строковую переменную "SomeValue"
161161 // если SomeValue имеет значение по умолчанию, запись не сохраняется,
162162 // поэтому сохраняются только [значения,] отличающиеся от значения по умолчанию.
163163 // Таким образом, xml остается коротким, и значения по умолчанию могут измениться в будущем.
164164 Config.SetDeleteValue('Path/To/Some/Value',SomeValue,'Default');
165165 Config.SetDeleteValue('Path/To/Some/Integer',SomeInteger,3);
166166 Config.SetDeleteValue('Path/To/Some/Boolean',SomeBoolean,true);
167167 // далее [по коду] еще overloads-инструкции для SetDeleteValue,
168168 // которые [всплывают в редакторе кода по нажатию] <Ctrl>+<Space>
169169 finally
170170 Config.Free;
171171 end;
172172
173173 except
174174 on E: Exception do begin
175175 DebugLn(['Saving mysettings.xml failed: ',E.Message]);
176176 end;
177177 end;
178178
179179 // загрузка настроек
180180 try
181181 Config:=GetIDEConfigStorage('mysettings.xml',true);
182182 try
183183 // чтение версии конфигурации
184184 FileVersion:=Config.GetValue('Path/To/The/Version',0);
185185 // чтение строковой переменной "SomeValue". Если запись не существует, используется
186186 // значение по умолчанию
187187 SomeValue:=Config.GetValue('Path/To/Some/Value','Default');
188188 SomeInteger:=Config.GetValue('Path/To/Some/Integer',3);
189189 SomeBoolean:=Config.GetValue('Path/To/Some/Boolean',true);
190190 finally
191191 Config.Free;
192192 end;
193193 except
194194 on E: Exception do begin
195195 DebugLn(['Loading mysettings.xml failed: ',E.Message]);
196196 end;
197197 end;
198198end;
199199```
200200
201201На заметку:
202202
203203- Каждый плагин IDE должен использовать свой собственный файл конфигурации. Особенно вы не должны использовать стандартные файлы опций IDE, такие как [[editoroptions.xml]] или [[environmentmentoptions.xml]].
204204- GetIDEConfigStorage при загрузке проверяет, существует ли файл и, если нет, копирует шаблон из вторичного каталога конфигурации.
205205- Начиная с версии 0.9.31 вы можете использовать эту функцию для загрузки файла вне основного каталога конфигурации.
206206
207207# Компоненты
208208
209209## Расширение существующих компонентов
210210
211211Источник: [1](http://lazarus.freepascal.org/index.php/topic,17733.msg98425.html#msg98425) Это обычная настройка существующих компонентов LCL, например, если вы хотите добавить свойства.
212212
213213Добавьте необходимые свойства с соответствующими методами установки и получения и полями хранения.
214214
215215Затем создайте их экземпляр «вручную», предоставив компонент-владелец (для последующей обработки), и установите \[свойство\] Parent и, возможно, \[свойства\] Top и Left и любые другие значения по умолчанию, необходимые для вашего компонента при инициализации.
216216
217217Когда вы убедитесь, что ваш настроенный компонент отлажен, добавьте вызов `RegisterComponent()`, чтобы прикрепить его к палитре компонентов IDE и избавьте вас от необходимости выполнять код установки вручную (посмотрите на исходник любого компонента, чтобы узнать, как это сделать).
218218
219219Вот простой пример:
220220
221221``` pascal
222222unit Unit1;
223223
224224{$mode objfpc}{$H+}
225225
226226interface
227227
228228uses
229229 Classes, SysUtils, Forms, StdCtrls;
230230
231231type
232232 TEdX = class(TEdit)
233233 private
234234 FNewIntProp: integer;
235235 FNewStrProp: string;
236236 procedure SetNewIntProp(AValue: integer);
237237 procedure SetNewStrProp(AValue: string);
238238 public
239239 constructor Create(theComponent: TComponent); override;
240240 property NewIntProp: integer read FNewIntProp write SetNewIntProp;
241241 property NewStrProp: string read FNewStrProp write SetNewStrProp;
242242 end;
243243
244244 TForm1 = class(TForm)
245245 procedure FormCreate(Sender: TObject);
246246 private
247247 edX: TEdX;
248248 public
249249 end;
250250
251251var
252252 Form1: TForm1;
253253
254254implementation
255255
256256{ TForm1 }
257257
258258procedure TForm1.FormCreate(Sender: TObject);
259259begin
260260 edX:= TEdX.Create(Self);
261261 edX.Parent:= Self;
262262 edX.Caption:= IntToStr(edX.NewIntProp);
263263 Caption:= edX.NewStrProp;
264264end;
265265
266266{$R *.lfm}
267267
268268{ TEdX }
269269
270270procedure TEdX.SetNewIntProp(AValue: integer);
271271begin
272272 if FNewIntProp=AValue then Exit;
273273 FNewIntProp:=AValue;
274274 // добавьте свой код здесь
275275end;
276276
277277procedure TEdX.SetNewStrProp(AValue: string);
278278begin
279279 if FNewStrProp=AValue then Exit;
280280 FNewStrProp:=AValue;
281281 // добавьте свой код здесь
282282end;
283283
284284constructor TEdX.Create(theComponent: TComponent);
285285begin
286286 inherited Create(theComponent);
287287 FNewStrProp:= 'new string property value';
288288 FNewIntProp:= 99;
289289end;
290290
291291end.
292292```
293293
294294## Написание компонент
295295
296296*Основная статья: [[How To Write Lazarus Component/ru|How To Write Lazarus Component]]*
297297
298298Вы можете создавать новые компоненты через редактор пакетов.
299299
300300Создайте или откройте пакет, нажмите **add**(добавить), нажмите **New Component** (Новый компонент), заполните пункты: Ancestor Type(Тип предка) = TButton, New class name (Имя нового класса) = TMyButton, palette page (страница палитры) = Misc, Unit file name (имя файла модуля) = mybutton.pas (этот файл будет создан), имя модуля MyButton, и нажмите кнопку **ok**.
301301
302302### Предоставление новому компоненту иконки для палитры компонентов
303303
304304Создайте файл изображения в формате .bmp, .xpm или .png с тем же именем, что и класс компонента. Например, *tmybutton.png* и сохраните его в исходном каталоге пакета. Изображение может быть создано любой графической программой (например, GIMP \[или IncScape\]) и должно быть не больше 24x24 пикселей. Затем преобразуйте изображение в файл ресурсов с помощью инструмента lazres, который можно найти в каталоге lazarus/tools:
305305
306306``` bash
307307~/lazarus/tools/lazres mybutton.lrs tmybutton.png
308308```
309309
310310> **Note:** Лаззарус trunk/1.4+? использует файлы ресурсов .res взамен .lrs-файлов
311311
312312``` bash
313313~/lazarus/tools/lazres mybutton.res tmybutton.png
314314```
315315
316316Это создаст include-файл паскаля, который используется в разделе initialization mybutton.pas:
317317
318318``` pascal
319319initialization
320320 {$I mybutton.lrs}
321321 // или в более новой версии Lazarus - синтаксис docheck
322322 {$R mybutton.res}
323323```
324324
325325Установите пакет.
326326
327327### Скрытие компонента в палитре компонентов
328328
329329Пакет IDEIntf, модуль componentreg:
330330
331-`IDEComponentPalette.FindComponent('TButton').Visible:=false;`
331+``` pascal
332+IDEComponentPalette.FindComponent('TButton').Visible:=false;
333+```
332334
333335## Написание редактора компонента
334336
335337Редактор компонента обрабатывает такие вещи, как двойной щелчок по компоненту в конструкторе или добавление пунктов меню при щелчке правой кнопкой мыши по компоненту. Написать редактор компонентов легко. Посмотрите модуль componententeditors.pas пакета IDEIntf для \[просмотра\] кучи примеров. Например, чтобы показать редактор при двойном щелчке, см. TCheckListBoxComponentEditor.
336338
337339## Написание редакторов свойств
338340
339341Каждый тип свойства (integer, string, TFont, ...) в Инспекторе объектов нуждается в редакторе свойств. Если у вашего компонента есть свойство *Password* типа string, вы можете определить редактор свойств для вашего конкретного класса компонента со именем свойства *Password* типа string. Модуль propedits.pp пакета IDEIntf содержит многие стандартные редакторы свойств, используемые самой IDE. Например, TStringPropertyEditor является редактором свойств по умолчанию для всех строк, в то время как TComponentNamePropertyEditor является более конкретным и обрабатывает только TComponent.Name. Смотрите \[исходный код\] модуля для \[получения\] множества примеров.
340342
341343### Сокрытие свойства в инспекторе объектов
342344
343345Существует специальный редактор свойств для сокрытия \[свойств\]:
344346
345347``` pascal
346348 RegisterPropertyEditor(TypeInfo(TAnchorSide), TControl, 'AnchorSideLeft', THiddenPropertyEditor);
347349```
348350
349351### Поиск редактора свойств, используемого для свойства
350352
351353``` pascal
352354uses Classes, TypInfo;
353355var
354356 Instance: TPersistent; // ваш экземпляр
355357 PropInfo: PPropInfo;
356358 EdClass: TPropertyEditorClass;
357359begin
358360 PropInfo:=GetPropInfo(Instance.ClassType,'Name'); // замените Name именем свойства, которое вы ищете
359361 GetEditorClass(PropInfo, Instance);
360362end;
361363```
362364
363365# Формы
364366
365367IDE позволяет легко создавать потомков форм и фреймов. Эти формы могут иметь новые published-компоненты и новые published-методы. Но, когда вы добавляете новые published-свойства, они не доступны через инспектор объектов. Они работают только во время выполнения \[приложения\]. Методы в IDE являются поддельными, они не могут быть выполнены. В среде IDE можно создавать компоненты, поскольку их классы зарегистрированы в палитре компонентов. Ваши новые свойства существуют только в вашем исходном коде. IDE пока не может их подделать. Вот почему вы должны зарегистрировать новый класс. Это означает \[, что вы должны\]:
366368
367369- Создать пакет времени разработки (или расширить существующий)
368370- Ваша форма должна быть в модуле этого пакета
369371
370372``` pascal
371373...
372374interface
373375
374376uses FormEditingIntf, Forms;
375377
376378type
377379 TYourForm = class(TForm)
378380 private
379381 FYourProperty: integer;
380382 published
381383 property YourProperty: integer read FYourProperty write FYourProperty;
382384 end;
383385
384386procedure Register;
385387
386388implementation
387389
388390procedure Register;
389391begin
390392 FormEditingHook.RegisterDesignerBaseClass(TYourForm);
391393end;
392394...
393395```
394396
395397- Проверить \[наличие процедуры\] "Register" в редакторе пакетов для этого модуля.
396398- Установить пакет в IDE
397399
398400# Дизайнер
399401
400402## Написание дизайнера-посредника
401403
402404Стандартный конструктор позволяет визуально редактировать элементы управления LCL, тогда как все остальные отображаются в виде значков (например, TOpenDialog или TDataSource). Чтобы визуально редактировать элемент управления не \[из библиотеки\] LCL, вам нужно создать **designer mediator** (дизайнер-посредник). Он может быть использован для разработки веб-страниц, диаграмм UML или других наборов виджетов, таких как [[fpGUI]]. Полный пример приведен в examples/designnonlcl/.
403405
404406- Установите пакет с примерами examples/designnonlcl/notlcldesigner.lpk и перезапустите IDE. Это зарегистрирует дизайнер-посредник для компонентов TMyWidget и добавит новые компоненты TMyButton, TMyGroupBox в палитру компонентов.
405407- Откройте проект с примерами examples/designnonlcl/project/NonLCL1.lpi.
406408- Откройте unit1.pas и покажите дизайнер форм (F12). Вы должны увидеть компоненты в виде красных прямоугольников, которые можно выделять, перемещать и изменять их размер, как элементы управления LCL.
407409
408410## Создание нового уникального имени компонента
409411
410412``` pascal
411413uses FormEditingIntf;
412414
413415...
414416
415417NewName:=FormEditingHook.CreateUniqueComponentName(AComponent);
416418
417419// Или, если вам нужно создать имя перед созданием компонента:
418420
419421NewName:=FormEditingHook.CreateUniqueComponentName(ComponentClassName,OwnerComponent);
420422// ComponentClassName будет использоваться в качестве префикса без начального T.
421423// OwnerComponent является новым владельцем нового компонента.
422424```
423425
424426## Выбор компонента в конструкторе/инспекторе объектов
425427
426428``` pascal
427429uses propedits;
428430..
429431GlobalDesignHook.SelectOnlyThis(AComponent);
430432```
431433
432434## Получение файла модуля, дизайнера формы
433435
434436``` pascal
435437uses ProjectIntf, LazIDEIntf, ComponentEditors;
436438...
437439// открываем файл
438440if LazarusIDE.DoOpenEditorFile(Filename,-1,-1,[ofAddToRecent])<>mrOk then exit;
439441// получаем интерфейс файла
440442aFile:=LazarusIDE.ActiveProject.FindFile(Filename,[]);
441443// получаем дизайнер
442444aDesigner:=TComponentEditorDesigner(LazarusIDE.GetDesignerWithProjectFile(AFile,true));
443445if aDesigner=nil then
444446 exit; // этот модуль не имеет ресурса (форма, фрейм, модуль данных и т.д.)
445447// получаем форму
446448aForm:=aDesigner.Form;
447449```
448450
449451## Сохранение модуля, дизайнера формы
450452
451453``` pascal
452454uses LazIDEIntf;
453455...
454456if LazarusIDE.DoSaveEditorFile(Filename,[])<>mrOk then exit;
455457```
456458
457459## Сохранение формы дизайнера как кода Паскаль
458460
459461- Используйте функцию **FormEditingHook.SaveComponentAsPascal** модуля *FormEditingfIntf*. См. *examples/pascalstream/CopyAsPasPkg/copyaspasdemounit1.pas*.
460462
461463# Обработчики событий
462464
463465В IDE есть несколько событий, для которых плагины могут добавлять свои собственные обработчики.
464466
465467## События дизайнера
466468
467469В propedits.pp есть объект "GlobalDesignHook", который поддерживает несколько событий для проектирования. Каждое событие вызывает список обработчиков. Обработчики по умолчанию добавляются в среду IDE. Вы можете добавить свои собственные обработчики с помощью методов AddHandlerXXX и RemoveHandlerXXX. Они будут вызваны перед обработчиками по умолчанию.
468470
469471Примеры:
470472
471473- Добавление вашего обработчика (это обычно делается в конструкторе вашего объекта):
472474
473-` GlobalDesignHook.AddHandlerPersistentAdded(@YourOnPersistentAdded);`
475+```text
476+ GlobalDesignHook.AddHandlerPersistentAdded(@YourOnPersistentAdded);
477+```
474478
475479- Удаление вашего обработчика:
476480
477-` GlobalDesignHook.RemoveHandlerPersistentAdded(@YourOnPersistentAdded);`
481+```text
482+ GlobalDesignHook.RemoveHandlerPersistentAdded(@YourOnPersistentAdded);
483+```
478484
479485- Вы можете удалить все обработчики одновременно. Например, это хорошая идея - добавить эту строку в деструктор вашего объекта:
480486
481-` GlobalDesignHook.RemoveAllHandlersForObject(Self);`
487+```text
488+ GlobalDesignHook.RemoveAllHandlersForObject(Self);
489+```
482490
483491Обработчики GlobalDesignHook:
484492
485493- Поиск корня
486494 - ChangeLookupRoot - Вызывается при изменении "LookupRoot". "LookupRoot" является объектом-владельцем выбранных компонентов. Обычно это TForm.
487495- Методы
488496 - CreateMethod
489497 - GetMethodName
490498 - GetMethods
491499 - MethodExists
492500 - RenameMethod
493501 - ShowMethod
494502 - MethodFromAncestor
495503 - ChainCall
496504- Компоненты
497505 - GetComponent
498506 - GetComponentName
499507 - GetComponentNames
500508 - GetRootClassName
501509 - AddClicked - Вызывается, когда пользователь выбирает класс компонента и щелкает дизайнер, чтобы добавить новый компонент. Вы можете изменить класс компонента и родительский элемент.
502510 - ComponentRenamed - Вызывается, когда компонент был переименован
503511- Объекты TPersistent
504512 - PersistentAdded - Вызывается при добавлении нового TPersistent в LookupRoot
505513 - PersistentDeleting - Вызывается до освобождения TPersistent.
506514 - DeletePersistent - Вызывается IDE для удаления TPersistent.
507515 - GetSelectedPersistents - Вызывается при получении текущего выбора TPersistent.
508516 - SetSelectedPersistents - Вызывается при настройке текущего выбора TPersistent.
509517 - GetObject
510518 - GetObjectName
511519 - GetObjectNames
512520- Изменение
513521 - Modified
514522 - Revert
515523 - RefreshPropertyValues
516524- Выбор
517525 - SetSelection
518526 - GetSelection
519527
520528### Примеры для событий дизайнера
521529
522530#### Пример: когда \[на родителя\] помещается новый компонент, перемещать элемент управления в дочерний элемент
523531
524532``` pascal
525533...
526534type
527535 TYourDesignerExtension = class
528536 private
529537 function AddClicked(ADesigner: TIDesigner;
530538 MouseDownComponent: TComponent; Button: TMouseButton;
531539 Shift: TShiftState; X, Y: Integer;
532540 var AComponentClass: TComponentClass;
533541 var NewParent: TComponent): boolean of object;
534542 public
535543 constructor Create;
536544 destructor Destroy; override;
537545 end;
538546
539547...
540548constructor TYourDesignerExtension.Create;
541549begin
542550 // регистрация вашего обработчика
543551 GlobalDesignHook.AddHandlerAddClicked(@AddClicked);
544552end;
545553
546554destructor TYourDesignerExtension.Destroy;
547555begin
548556 // удаление вашего обработчика
549557 GlobalDesignHook.RemoveHandlerAddClicked(@AddClicked);
550558end;
551559
552560function TYourDesignerExtension.AddClicked(ADesigner: TIDesigner;
553561 MouseDownComponent: TComponent; Button: TMouseButton;
554562 Shift: TShiftState; X, Y: Integer;
555563 var AComponentClass: TComponentClass;
556564 var NewParent: TComponent): boolean of object;
557565begin
558566 // в этом примере TYourControl - это пользовательский элемент управления с ChildControl.
559567 // Всякий раз, когда пользователь помещает элемент управления на TYourControl, вместо добавления
560568  // нового элемента управления на TYourControl, [этот] новый элемент управления добавляется как дочерний элемент
561569  // [имеющегося] ChildControl.
562570 // создание
563571 if MouseDownComponent is TYourControl then
564572 NewParent:=TYourControl(MouseDownComponent).ChildControl;
565573 Result:=true;
566574end;
567575```
568576
569577### Отключение обработчика мыши в \[режиме\] дизайнера
570578
571579Обычно дизайнер ловит все события мыши компонента. Если ваш пользовательский элемент управления должен обрабатывать дескриптор событий мыши, вы можете либо установить **csDesignInteractive** **ControlStyle**, либо вы можете точно управлять им через сообщение *CM_DESIGNHITTEST* в вашем элементе управления:
572580
573581``` pascal
574582type
575583 TYourControl = class(TCustomControl)
576584 protected
577585 procedure CMDesignHitTest(var Message: TLMessage); message CM_DESIGNHITTEST;
578586 end;
579587...
580588procedure TYourControl.CMDesignHitTest(var Message: TLMessage);
581589var
582590 p: TSmallPoint;
583591 aShiftState: TShiftState;
584592begin
585593 aShiftState:=KeysToShiftState(PtrUInt(Message.WParam));
586594 p:=TSmallPoint(longint(Message.LParam));
587595 debugln(['TForm1.CMDesignHitTest ShiftState=',dbgs(aShiftState),' x=',p.x,' y=',p.y]);
588596 if SkipDesignerMouseHandler then
589597 Message.Result:=1; // теперь дизайнер вызывает обычные методы MouseUp, MouseMove и MouseDown.
590598end;
591599```
592600
593601## Получение уведомлений при изменении дизайнера форм
594602
595603Каждая разработанная форма LCL имеет конструктор типа TIDesigner. В среде IDE создаются конструкторы типа TComponentEditorDesigner, определенные в компонентных компонентах модуля IDEIntf. Например:
596604
597605``` pascal
598606procedure TYourAddOn.OnDesignerModified(Sender: TObject);
599607var
600608 IDEDesigner: TComponentEditorDesigner;
601609begin
602610 IDEDesigner:=TComponentEditorDesigner(Sender);
603611 ...
604612end;
605613
606614procedure TYourAddOn.ConnectDesignerForm(Form1: TCustomForm);
607615var
608616 IDEDesigner: TComponentEditorDesigner;
609617begin
610618 IDEDesigner:=TComponentEditorDesigner(Form1.Designer);
611619 IDEDesigner.AddHandlerModified(@OnDesignerModified);
612620end;
613621```
614622
615623## События проекта
616624
617625Эти события определены в модуле LazIDEIntf.
618626
619627- **LazarusIDE.AddHandlerOnProjectClose**: вызывается перед закрытием проекта
620628- **LazarusIDE.AddHandlerOnProjectOpened**: вызывается после полного открытия проекта (например, все необходимые пакеты были загружены, модули были открыты в редакторе исходного кода)
621629- **LazarusIDE.AddHandlerOnSavingAll**: вызывается перед тем, как IDE сохраняет все
622630- **LazarusIDE.AddHandlerOnSavedAll**: вызывается после того, как IDE сохранил все
623631- **LazarusIDE.AddHandlerOnProjectBuilding**: вызывается перед тем, как IDE создаст проект
624632- **LazarusIDE.AddHandlerOnProjectDependenciesCompiling**: вызывается перед тем, как IDE компилирует пакетные зависимости проекта
625633- **LazarusIDE.AddHandlerOnProjectDependenciesCompiled**: вызывается после компиляции зависимостей пакета IDE проекта
626634- **LazarusIDE.AddHandlerOnProjectBuildingFinished**: вызывается после того, как IDE собрал проект (успешно или нет) (начиная с 1.5)
627635
628636## Другие события IDE
629637
630638**uses** *LazIDEIntf;*
631639
632640Вызовите их в процедуре регистрации вашего пакета:
633641
634642- **LazarusIDE.AddHandlerOnIDERestoreWindows**: вызывается, когда IDE восстанавливает свои окна (перед открытием первого проекта)
635643- **LazarusIDE.AddHandlerOnIDEClose**: вызывается, когда IDE закрывается (после запроса закрытия, поэтому больше нет интерактивности)
636644- **LazarusIDE.AddHandlerOnQuickSyntaxCheck**: вызывается при выполнении пункта меню или ярлыка для быстрой проверки синтаксиса
637645- **LazarusIDE.AddHandlerOnLazarusBuilding**: вызывается перед тем, как IDE собирает Lazarus IDE (начиная с 1.5)
638646- **LazarusIDE.AddHandlerOnLazarusBuildingFinished**: вызывается после того, как IDE собирает Lazarus IDE (начиная с 1.5)
639647- **LazarusIDE.AddHandlerGetFPCFrontEndParams**: вызывается, когда IDE получает параметры клиентского инструмента интерфейса 'fpc' (начиная с 1.5)
640648- **LazarusIDE.AddHandlerGetFPCFrontEndPath**: вызывается, когда IDE получает параметры клиентского инструмента интерфейса 'fpc' (начиная с 1.5)
641649- **LazarusIDE.AddHandlerOnUpdateIDEComponentPalette**: ?
642650- **LazarusIDE.AddHandlerOnUpdateComponentPageControl**: ?
643651- **LazarusIDE.AddHandlerOnShowDesignerFormOfSource**: вызывается после показа конструктора формы для редактора кода (AEditor может быть nil!) (начиная с 1.5)
644652- **LazarusIDE.AddHandlerOnShowSourceOfActiveDesignerForm**: вызывается после показа кода формы дизайнера (начиная с 1.5)
645653- **LazarusIDE.AddHandlerOnChangeToolStatus**: вызывается, когда IDEToolStatus изменяется (например, itNone-\> itBuilder и т. д.) (начиная с 1.5)
646654
647655Вызовите их в разделе инициализации одного из модулей:
648656
649657- **AddBootHandler**
650658 - AddBootHandler(**libhTransferMacrosCreated**,@YourProc): вызывается после создания IDEMacros (начиная с версии 1.3)
651659 - AddBootHandler(**libhEnvironmentOptionsLoaded**,@YourProc): вызывается после загрузки параметров среды (начиная с версии 1.3)
652660
653661# Проект
654662
655663## Текущий проект
656664
657665Текущий основной проект может быть получен \[при помощи\] LazarusIDE.ActiveProject. (модуль LazIDEIntf)
658666
659667## Все модули текущего проекта
660668
661669Обратите внимание, что термин «юниты проекта» неоднозначен.
662670
663671- Инспектор проектов показывает список файлов .lpi. Проект может не использовать все эти модули на всех платформах, и, возможно, разработчик забыл добавить все используемые модули.
664672- Модули из использованных пакетов не являются модулями проекта.
665673
666674### Все модули инспектора проекта
667675
668676Чтобы перебрать все паскалевские модули, перечисленные в инспекторе проектов, вы можете использовать, например:
669677
670678``` pascal
671679uses
672680 LCLProc, FileUtil, LazIDEIntf, ProjectIntf;
673681
674682procedure ListProjectUnits;
675683var
676684 LazProject: TLazProject;
677685 i: Integer;
678686 LazFile: TLazProjectFile;
679687begin
680688 LazProject:=LazarusIDE.ActiveProject;
681689 if LazProject<>nil then
682690 for i:=0 to LazProject.FileCount-1 do
683691 begin
684692 LazFile:=LazProject.Files[i];
685693 if LazFile.IsPartOfProject
686694 and FilenameIsPascalUnit(LazFile.Filename)
687695 then
688696 debugln(LazFile.Filename);
689697 end;
690698end;
691699```
692700
693701### Все используемые модули проекта
694702
695703Чтобы найти все используемые в настоящее время модули проекта/пакета, вы можете использовать следующее. Обратите внимание, что в среде IDE необходимо проанализировать все модули, поэтому это может занять некоторое время.
696704
697705``` pascal
698706uses
699707 LazLoggerBase, LazIDEIntf, ProjectIntf;
700708
701709procedure ListProjectUnits;
702710var
703711 LazProject: TLazProject;
704712 i: Integer;
705713begin
706714 LazProject:=LazarusIDE.ActiveProject;
707715 if LazProject<>nil then
708716 begin
709717 Units:=LazarusIDE.FindUnitsOfOwner(LazProject,[fuooListed,fuooUsed]); // добавьте fuooPackages, чтобы включить модули из пакетов
710718 try
711719 for i:=0 to Units.Count-1 do
712720 debugln('Filename=',Units[i]);
713721 finally
714722 Units.Free;
715723 end;
716724 end;
717725end;
718726```
719727
720728## Файлы .lpr, .lpi и .lps проекта
721729
722730``` pascal
723731uses
724732 LCLProc, FileUtil, ProjectIntf, LazIDEIntf;
725733var
726734 LazProject: TLazProject;
727735begin
728736 LazProject:=LazarusIDE.ActiveProject;
729737 // у каждого проекта есть файл .lpi:
730738 DebugLn(['Файл проекта lpi: ',LazProject.ProjectInfoFile]);
731739
732740 // если информация о сеансе проекта хранится в отдельном файле .lps:
733741 if LazProject.SessionStorage<>pssNone then
734742 DebugLn(['Файл проекта lps: ',LazProject.ProjectSessionFile]);
735743
736744 // Если у проекта есть файл .lpr, то он является основным исходным файлом:
737745 if (LazProject.MainFile<>nil)
738746 and (CompareFileExt(LazProject.MainFile.Filename,'lpr')=0) then
739747 DebugLn(['Проект имеет файл lpr: ',LazProject.MainFile.Filename]);
740748end;
741749```
742750
743751## Имя исполняемого / целевого файла проекта
744752
745753Существует макрос \$(TargetFile), который можно использовать в путях и внешних инструментах. Вы можете запросить макрос в коде:
746754
747755``` pascal
748756uses MacroIntf;
749757
750758function MyGetProjectTargetFile: string;
751759begin
752760 Result:='$(TargetFile)';
753761 if not IDEMacros.SubstituteMacros(Result) then
754762 raise Exception.Create('невозможно получить целевой файл проекта');
755763end;
756764```
757765
758766См. здесь для более полной информации по макросам: [[IDE Macros in paths and filenames/ru|Макросы IDE в путях и именах файлов]].
759767
760768## Добавление своего собственного типа проекта
761769
762770Вы можете добавлять \[свои\] пункты в диалоговое окно 'New ...':
763771
764772- Смотрите модуль ProjectIntf пакета IDEIntf.
765773- См. [[Project Templates/ru|Шаблоны проекта]]
766774
767775## Добавление своих собственных типов файлов
768776
769777Вы можете добавлять \[свои\] пункты в диалоговое окно 'New ...':
770778
771779- Смотрите модуль ProjectIntf пакета IDEIntf.
772780- Выбрав базовый класс TFileDescPascalUnit для обычных модулей или TFileDescPascalUnitWithResource для новой формы/модуля данных.
773781
774782### Добавление нового типа файла
775783
776784``` pascal
777785uses ProjectIntf;
778786...
779787 { TFileDescText }
780788
781789 TFileDescMyText = class(TProjectFileDescriptor)
782790 public
783791 constructor Create; override;
784792 function GetLocalizedName: string; override;
785793 function GetLocalizedDescription: string; override;
786794 end;
787795...
788796
789797procedure Register;
790798
791799implementation
792800
793801procedure Register;
794802begin
795803 RegisterProjectFileDescriptor(TFileDescMyText.Create,FileDescGroupName);
796804end;
797805
798806{ TFileDescMyText }
799807
800808constructor TFileDescMyText.Create;
801809begin
802810 inherited Create;
803811 Name:='MyText'; // не переводите эту [строку]
804812 DefaultFilename:='text.txt';
805813 AddToProject:=false;
806814end;
807815
808816function TFileDescText.GetLocalizedName: string;
809817begin
810818 Result:='My Text'; // замените это строкой из resourcestring
811819end;
812820
813821function TFileDescText.GetLocalizedDescription: string;
814822begin
815823 Result:='Пустой текстовый файл';
816824end;
817825```
818826
819827### Добавление нового типа формы
820828
821829``` pascal
822830uses ProjectIntf;
823831
824832...
825833 TFileDescPascalUnitWithMyForm = class(TFileDescPascalUnitWithResource)
826834 public
827835 constructor Create; override;
828836 function GetInterfaceUsesSection: string; override;
829837 function GetLocalizedName: string; override;
830838 function GetLocalizedDescription: string; override;
831839 end;
832840...
833841
834842procedure Register;
835843
836844implementation
837845
838846procedure Register;
839847begin
840848 RegisterProjectFileDescriptor(TFileDescPascalUnitWithMyForm.Create,FileDescGroupName);
841849end;
842850
843851{ TFileDescPascalUnitWithMyForm }
844852
845853constructor TFileDescPascalUnitWithMyForm.Create;
846854begin
847855 inherited Create;
848856 Name:='MyForm'; // не переводите эту [строку]
849857 ResourceClass:=TMyForm;
850858 UseCreateFormStatements:=true;
851859end;
852860
853861function TFileDescPascalUnitWithMyForm.GetInterfaceUsesSection: string;
854862begin
855863 Result:='Classes, SysUtils, MyWidgetSet';
856864end;
857865
858866function TFileDescPascalUnitWithForm.GetLocalizedName: string;
859867begin
860868 Result:='MyForm'; // замените это строкой из resourcestring
861869end;
862870
863871function TFileDescPascalUnitWithForm.GetLocalizedDescription: string;
864872begin
865873 Result:='Создать новую MyForm из примера пакета NotLCLDesigner';
866874end;
867875```
868876
869877## Сохранение пользовательских значений в \[файлах\] lpi/lps
870878
871879Вы можете хранить свои собственные данные с помощью пар имя/значение в CustomData и CustomSessionData.
872880
873-`LazarusIDE.ActiveProject.CustomData['Name']:=Value; // хранится в lpi - x-platform, общие данные`\
874-`LazarusIDE.ActiveProject.CustomSessionData['Name']:=Value; // хранится в lpi - x-platform, общие данные`
881+``` pascal
882+LazarusIDE.ActiveProject.CustomData['Name']:=Value; // хранится в lpi - x-platform, общие данные
883+LazarusIDE.ActiveProject.CustomSessionData['Name']:=Value; // хранится в lpi - x-platform, общие данные
884+```
875885
876886# Пакеты
877887
878888Вы можете выполнять различные действия с [[Lazarus Packages/ru|пакетами]]:
879889
880890## Поиск во всех пакетах
881891
882892Переберите все пакеты, загруженные в IDE (начиная с 0.9.29).
883893
884894``` pascal
885895uses PackageIntf;
886896...
887897for i:=0 to PackageEditingInterface.GetPackageCount-1 do
888898 writeln(PackageEditingInterface.GetPackages(i).Name);
889899```
890900
891901## Поиск в пакетах с \[определенным\] именем
892902
893903``` pascal
894904uses PackageIntf;
895905...
896906var
897907 Pkg: TIDEPackage;
898908begin
899909 Pkg:=PackageEditingInterface.FindPackageWithName('LCL');
900910 if Pkg<>nil then
901911 ...
902912end;
903913```
904914
905915> **Note:** FindPackageWithName не открывает редактор пакетов. Для этого используйте DoOpenPackageWithName.
906916
907917## Получение имени файла lpk установленного пакета
908918
909919``` pascal
910920uses PackageIntf;
911921...
912922var
913923 Pkg: TIDEPackage;
914924begin
915925 Pkg:=PackageEditingInterface.FindPackageWithName('LCL');
916926 if Pkg<>nil then
917927 LPKFilename:=Pkg.Filename;
918928end;
919929```
920930
921931## Установка пакетов
922932
923933> **Note:** Устанавливайте только пакеты с плагинами IDE. Установка других пакетов может привести к нестабильной работе среды IDE.
924934
925935``` pascal
926936uses PackageIntf, contnrs;
927937...
928938 PkgList:=TObjectList.create(true);
929939 try
930940 Pkg:=TLazPackageID.Create;
931941 Pkg.Name:='Cody';
932942 PkgList.Add(Pkg);
933943 // проверьте, может ли IDE найти cody.lpk и все зависимости
934944 // Среда IDE покажет некоторые предупреждения/подтверждения, если что-то выглядит странно.
935945 if not PackageEditingInterface.CheckInstallPackageList(PkgList,[]) then
936946 exit;
937947 // в этом примере мы [это] уже проверили, поэтому пропустите предупреждения
938948 // и пересоберите IDE
939949 if PackageEditingInterface.InstallPackages(PkgList,[piiifSkipChecks,piiifRebuildIDE])<>mrOK then
940950 exit;
941951 finally
942952 PkgList.Free;
943953 end;
944954```
945955
946956## Открытие файла пакета (lpk)
947957
948958``` pascal
949959uses PackageIntf, FileUtil;
950960...
951961var
952962 pkg: TIDEPackage;
953963begin
954964 if PackageEditingInterface.DoOpenPackageFile(LPKFilename,[pofAddToRecent],false)<>mrOk then
955965 exit;
956966 Pkg:=PackageEditingInterface.FindPackageWithName(ExtractFilenameOnly(LPKFilename));
957967 ...
958968end;
959969```
960970
961971> **Warning:** Среда IDE автоматически закрывает неиспользуемые пакеты в режиме ожидания. Никогда не храните ссылку на TIDEPackage.
962972
963973## Поиск пакета(-ов) модуля
964974
965975У вас есть имя файла модуля, например '/home/user/unit.pas', и \[если\] вы хотите знать, какому пакету(-ам) и проекту(-ам) он принадлежит, используйте это:
966976
967977``` pascal
968978uses Classes, PackageIntf, ProjectIntf;
969979...
970980var
971981 Owners: TFPList;
972982 i: Integer;
973983 o: TObject;
974984begin
975985 Owners:=PackageEditingInterface.GetPossibleOwnersOfUnit('/full/path/of/unit.pas',[]);
976986 if Owners=nil then begin
977987 // модуль не связан напрямую с проектом/пакетом
978988 // возможно модуль был по какой-то причине не добавлен, но доступен
979989 // поиск по всем путям модулей всех проектов/пакетов
980990 // Осторожно: это может привести к ложным попаданиям
981991 Owners:=PackageEditingInterface.GetPossibleOwnersOfUnit('/full/path/of/unit.pas',
982992 [piosfExcludeOwned,piosfIncludeSourceDirectories]);
983993 end;
984994 if Owners=nil then exit;
985995 try
986996 for i:=0 to Owners.Count-1 do begin
987997 o:=TObject(Owners[i]);
988998 if o is TIDEPackage then begin
989999 writeln('Owner is package ',TIDEPackage(o).Name);
9901000 end else if o is TLazProject then begin
9911001 writeln('Owner is project ',TLazProject(o).ProjectInfoFile);
9921002 end;
9931003 end;
9941004 finally
9951005 Owners.Free;
9961006 end;
9971007```
9981008
9991009# Окна
10001010
10011011Есть четыре основных типа окон IDE.
10021012
10031013- основная панель IDE - это Application.MainForm. Оно всегда присутствует.
10041014- плавающие / закрепляемые окна, такие как Редактор исходного кода, Инспекторы объектов и Сообщения.
10051015- модальные формы, такие как диалог поиска, диалоги настроек и вопросы.
10061016- подсказки и заполнение форм
10071017
10081018## Добавление нового закрепляемого окна IDE
10091019
10101020Что такое закрепляемое окно IDE: Окна, такие как Редактор исходного кода или Инспектор объектов, являются плавающими окнами, которые можно закрепить, если установлен пакет закрепления, а его состояние, положение и размер сохраняются и восстанавливаются при следующем запуске IDE. Для восстановления окна IDE нужен создатель, как определено в модуле **IDEWindowIntf** пакета IDEIntf. Каждое закрепляемое окно должно иметь уникальное имя. Не используйте общие имена, такие как 'FileBrowser', потому что это будет легко конфликтовать с другими пакетами. И не используйте короткие имена, такие как 'XYZ', потому что создатель отвечает за все формы, начинающиеся с этого имени.
10111021
10121022### Как зарегистрировать закрепляемое окно IDE
10131023
10141024Не забудьте выбрать длинное уникальное имя, которое является действительным идентификатором Паскаля. Ваше окно может иметь любой заголовок, который вы хотите.
10151025
10161026``` pascal
10171027uses SysUtils, IDEWindowIntf;
10181028...
10191029var MyIDEWindow: TMyIDEWindow = nil;
10201030
10211031procedure CreateMyIDEWindow(Sender: TObject; aFormName: string; var AForm: TCustomForm; DoDisableAutoSizing: boolean);
10221032begin
10231033 // проверяем имя
10241034 if CompareText(aFormName,MyIDEWindowName)<>0 then exit;
10251035 // создаем форму, если это еще не сделано, и отключаем автомасштабирование
10261036 IDEWindowCreators.CreateForm(MyIDEWindow,TMyIDEWindowm,DoDisableAutosizing,Application);
10271037 ... инициируем окно ...
10281038 AForm:=MyIDEWindow;
10291039end;
10301040
10311041procedure Register;
10321042begin
10331043 IDEWindowCreators.Add('MyIDEWindow',@CreateMyIDEWindow,nil,'100','50%','+300','+20%');
10341044 // стандартная граница формы - это:
10351045 // Left=100, Top=50% от [величины] Screen.Height, Width=300, Height=20% от [величины] Screen.Height
10361046 // когда IDE требуется экземпляр этого окна, она вызывает процедуру CreateMyIDEWindow.
10371047end;
10381048```
10391049
10401050### Отображение окна IDE
10411051
10421052> **Warning:** Не используйте \[процедуру\] Show.
10431053
1044-`Используйте:`
1054+```text
1055+Используйте:
1056+```
10451057
10461058``` pascal
10471059IDEWindowCreators.ShowForm(MyIDEWindow,false);
10481060```
10491061
10501062Это будет работать с \[механизмом\] пристыковки. Система пристыковки может обернуть форму в стыковочный узел. Параметр BringToFront указывает системе закрепления сделать форму и все ее родительские сайты видимыми и вывести сайт верхнего уровня вперед.
10511063
10521064### Заметки о IDEWindowCreators и SimpleLayoutStorage
10531065
10541066IDEWindowCreators.SimpleLayoutStorage просто хранит BoundsRect и WindowState всех форм, которые когда-то были открыты. Он используется как запасной вариант, если не установлен док-мастер. Он сохраняет состояние, даже если установлен DockMaster, поэтому, когда dockmaster удален, границы форм восстанавливаются.
10551067
10561068IDEWindowCreators используется всеми присоединяемыми формами для регистрации и отображения форм. При показе формы Создатель проверяет, установлен ли IDEDockMaster, и передает ему отображение. Если IDEDockMaster не установлен, он просто показывает форму. IDEDockMaster может использовать информацию в IDEWindowCreators для создания форм по именам и получить представление о том, где разместить форму при ее первом отображении. Для более подробной информации смотрите пакеты AnchorDockingDsgn и EasyDockMgDsgn.
10571069
10581070# CodeTools
10591071
10601072CodeTools - это пакет, предоставляющий огромное количество функций для анализа, поиска и изменения исходных текстов, а также некоторые основные функции для других языков. Вы можете использовать их также и без IDE. Рекомендуется сначала прочитать о CodeTools в целом, прежде чем использовать их в IDE: [[Codetools]].
10611073
10621074Перед вызовом любой из функций CodeTools в IDE вы должны зафиксировать текущие изменения редактора исходного кода в буферах CodeTools:
10631075
10641076``` pascal
10651077uses LazIDEIntf;
10661078...
10671079 // сохраняем изменения в редакторе исходного кода в codetools
10681080 LazarusIDE.SaveSourceEditorChangesToCodeCache(-1); // -1: фиксируем все редакторы исходного кода
10691081```
10701082
10711083## Добавление директивы ресурса в файл
10721084
10731085Это добавляет {\$R example.res} к модулю паскаля:
10741086
10751087``` pascal
10761088procedure AddResourceDirectiveToPascalSource(const Filename: string);
10771089var
10781090 ExpandedFilename: String;
10791091 CodeBuf: TCodeBuffer;
10801092begin
10811093 // убеждаемся, что имя файла обрезано [от концевых пробелов] и содержит полный путь
10821094 ExpandedFilename:=CleanAndExpandFilename(Filename);
10831095
10841096 // сохраняем изменения в редакторе исходного кода в codetools
10851097 LazarusIDE.SaveSourceEditorChangesToCodeCache(-1);
10861098
10871099 // загружаем файл
10881100 CodeBuf:=CodeToolBoss.LoadFile(ExpandedFilename,true,false);
10891101
10901102 // добавляем директиву ресурса
10911103 if not CodeToolBoss.AddResourceDirective(CodeBuf,'example.res') then
10921104 LazarusIDE.DoJumpToCodeToolBossError;
10931105end;
10941106```
10951107
10961108Codetools также предоставляет такие функции, как FindResourceDirective и RemoveDirective.
10971109
10981110## Получение путей поиска для модулей и включаемых файлов
10991111
11001112В среде IDE существует множество различных путей поиска из проектов, пакетов, каталога fpc и lazarus, и существует множество типов путей: до или после разрешения макросов, с унаследованными путями поиска или без них, как относительными или абсолютными путями. Все файлы в каталоге имеют одинаковый набор путей поиска. Вы можете получить пути поиска для каждого каталога, полностью решенного путем запроса codetools:
11011113
11021114``` pascal
11031115uses CodeToolManager;
11041116...
11051117
11061118Dir:=''; // пустой каталог для новых файлов и имеет те же настройки, что и каталог проекта
11071119
11081120// Получение путей поиска для включаемых файлов:
11091121Path:=CodeToolBoss.GetIncludePathForDirectory(Dir);
11101122
11111123// Получение путей поиска для модулей:
11121124// Этот путь поиска передается компилятору.
11131125// Он содержит выходные каталоги пакетов, но не каталоги с исходниками пакетов.
11141126Path:=CodeToolBoss.GetUnitPathForDirectory(Dir);
11151127
11161128// Могут быть дополнительные пути поиска модулей только для IDE (не передаются компилятору)
11171129Path:=CodeToolBoss.GetSrcPathForDirectory(Dir);
11181130
11191131// Полный путь поиска содержит также все исходные пути пакета для модулей:
11201132Path:=CodeToolBoss.GetCompleteSrcPathForDirectory(Dir);
11211133```
11221134
11231135# Редактор исходного кода
11241136
11251137## Активный редактор исходного кода
11261138
11271139``` pascal
11281140uses SrcEditorIntf;
11291141...
11301142Editor:=SourceEditorManagerIntf.ActiveEditor;
11311143if Editor=nil then exit;
11321144Filename:=Editor.FileName;
11331145ScreenPos:=Editor.CursorScreenXY;
11341146TextPos:=Editor.CursorTextXY;
11351147```
11361148
11371149# SynEdit
11381150
11391151## Получение настроек для TSynEdit
11401152
11411153Если у вас есть диалог с использованием TSynEdit, и вы хотите использовать тот же шрифт и настройки, которые использует редактор исходного кода:
11421154
11431155``` pascal
11441156uses SrcEditorIntf;
11451157...
11461158SourceEditorManagerIntf.GetEditorControlSettings(ASynEdit);
11471159```
11481160
11491161## Получение настроек для подсветки SynEdit
11501162
11511163Если у вас есть диалог, использующий TSynEdit с подсветкой, и вы хотите использовать те же цвета, что и для подсветки редактора исходного кода для этого языка, используйте:
11521164
11531165``` pascal
11541166uses SrcEditorIntf;
11551167...
11561168SourceEditorManagerIntf.GetHighlighterSettings(ASynHighlighter);
11571169```
11581170
11591171См. пример: TSQLStringsPropertyEditorDlg.Create in the unit [SQLStringsPropertyEditorDlg](http://svn.freepascal.org/svn/lazarus/trunk/components/sqldb/sqlstringspropertyeditordlg.pas).
11601172
11611173# Справка
11621174
11631175## Добавление справки для исходников
11641176
11651177Сначала создаем THelpDatabase:
11661178
11671179``` pascal
11681180HelpDB := TFPDocHTMLHelpDatabase(
11691181 HelpDatabases.CreateHelpDatabase('ANameOfYourChoiceForTheDatabase',
11701182 TFPDocHTMLHelpDatabase,true));
11711183HelpDB.DefaultBaseURL := 'http://your.help.org/';
11721184
11731185FPDocNode := THelpNode.CreateURL(HelpDB,
11741186 'Package1 - A new package',
11751187 'file://index.html');
11761188HelpDB.TOCNode := THelpNode.Create(HelpDB,FPDocNode);// один раз как оглавление TOC
11771189DirectoryItem := THelpDBISourceDirectory.Create(FPDocNode,'$(PkgDir)/lcl',
11781190 '*.pp;*.pas',false);// и один раз как обычная страница
11791191HelpDB.RegisterItem(DirectoryItem);
11801192```
11811193
11821194## Добавление строк в окно сообщений
11831195
11841196``` pascal
11851197unit IDEMsgIntf;
11861198...
11871199var Dir: String;
11881200begin
11891201 Dir:=GetCurrentDir;
11901202 IDEMessagesWindow.BeginBlock;
11911203 IDEMessagesWindow.AddMsg('unit1.pas(30,4) Error: Identifier not found "a"',Dir,0);
11921204 IDEMessagesWindow.EndBlock;
11931205end;
11941206```
11951207
11961208# Окно настроек IDE
11971209
11981210## Открытие параметров в определенном кадре
11991211
12001212``` pascal
12011213uses LazIDEIntf;
12021214...
12031215LazarusIDE.DoOpenIDEOptions(TYourIDEOptionsFrame);
12041216```
12051217
12061218# Прочее
12071219
12081220## Добавление макроса
12091221
12101222Вы можете добавить свои собственные макросы IDE:
12111223
12121224``` pascal
12131225uses MacroIntf, MacroDefIntf;
12141226
12151227procedure Register;
12161228begin
12171229 // регистрация макроса с фиксированным значением:
12181230 IDEMacros.Add(TTransferMacro.Create('MyMacro1','Value','Description',nil,[]));
12191231end;
12201232
12211233// регистрация макроса с динамическим значением требует метода объекта
12221234procedure TForm1.Init;
12231235begin
12241236 IDEMacros.Add(TTransferMacro.Create('MyMacro','Value','Description',@OnResolveMyMacro,[]));
12251237end;
12261238
12271239function TForm1.OnResolveMyMacro(const s: string; const Data: PtrInt;
12281240 var Abort: boolean): string;
12291241// s - это параметр. Например, $MyMacro(parameter)
12301242// Data - это экземпляр запроса. Может быть nil.
12311243// Если есть ошибка, установите Abort в true.
12321244// Результирующая строка может содержать макросы. Например, Result:='$(FPCVer)/$(TargetOS)';
12331245begin
12341246 Result:='MyValue';
12351247end;
12361248```
12371249
12381250## Отладка IDE
12391251
12401252- Скомпилируйте IDE как обычно, например, с помощью Tools/Build Lazarus. Убедитесь, что вы установили отладочные флаги, такие как -g или -gw2. Лучше всего использовать профиль "Debug IDE", который содержит много флагов, полезных для отладки.
12411253- Откройте проект ide\lazarus.lpi. Вы не можете напрямую скомпилировать этот проект.
12421254- Установите точки останова и пр. И запустите проект.
12431255
12441256## См. также
12451257
12461258- [[Creating IDE Help]]
12471259- [[Help protocol]]
12481260- [[How To Write Lazarus Component]]
12491261
12501262---
12511263*From the Free Pascal wiki, page "Extending the IDE/ru", as it stood on 2020-02-14 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