Sign in Join
Wiki copytemporary

Extending the IDE/de: what changed

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

Title: Extending the IDE/de

OldNewLine
1+# Erweitern der IDE
2+
3+## Überblick
4+
5+Die IDE unterstützt verschiedene Erweiterungen:
6+
7+Komponenten
8+Komponenten werden in der Palette installiert. Z.B. TButton erzeugt Buttons.
9+
10+Komponenten-Editoren
11+Komponenteneditoren werden benutzt, wenn Sie auf eine Komponente im Designer doppelklicken oder um einige extra Items im Popupmenü des Designers hinzuzufügen, indem man auf eine Komponente rechtsklickt.
12+
13+Eigenschafts-Editoren
14+Stellen die Editierfähigkeiten im Objektinspektor zur Verfügung.
15+
16+Experten
17+Das sind alle anderen Typen von Editoren. Sie registrieren neue Menüpunkte, Tastenkürzel oder erweitern andere Merkmale der IDE.
18+
19+Es gibt 2 Möglichkeiten, Ihre eigenen Plugins in Lazarus zu integrieren:
20+
21+1. Erstellen Sie ein Package, installieren Sie es und registrieren Sie das Plugin mit der Prozedur 'Register' in einer Unit.
22+2. Erweitern Sie den Lazarus Code und senden Sie Ihr SVN diff an die Lazarus-Mailing-Liste.
23+
24+# Menüpunkte
25+
26+Sie können neue Menüpunkte anfügen, bestehende Menüpunkte verstecken oder verschieben und Untermenüs oder Abschnitte hinzufügen. Für Ihre eigenen Formulare können Sie das TMainMenu/TPopupMenu registrieren, sodass andere Packages darauf zugreifen und Ihr Formular erweitern können. Die Unit **MenuIntf** des IDEIntf-Packages enthält die gesamte Registrierung für Menüs und viele Standard-Menüpunkte der IDE selbst.
27+
28+## Einen Menüpunkt hinzufügen
29+
30+Ein einzelner Menüpunkt wie 'View Object Inspector' wird **TIDEMenuCommand** genannt. Sie können einen erzeugen mit dem Befehl **RegisterIDEMenuCommand**, der in zwei Formen mit Unmengen von Parametern vorkommen kann:
31+
32+``` pascal
33+function RegisterIDEMenuCommand(Parent: TIDEMenuSection;
34+ const Name, Caption: string;
35+ const OnClickMethod: TNotifyEvent = nil;
36+ const OnClickProc: TNotifyProcedure = nil;
37+ const Command: TIDECommand = nil;
38+ const ResourceName: String = ''
39+ ): TIDEMenuCommand; overload;
40+function RegisterIDEMenuCommand(const Path, Name, Caption: string;
41+ const OnClickMethod: TNotifyEvent = nil;
42+ const OnClickProc: TNotifyProcedure = nil;
43+ const Command: TIDECommand = nil;
44+ const ResourceName: String = ''
45+ ): TIDEMenuCommand; overload;
46+```
47+
48+Der Unterschied zwischen diesen beiden Formen liegt nur darin, wie Sie die 'parent menu section' angeben. Geben Sie diesen Menüabschnitt direkt an oder oder indirekt mittels eines Pfades. Viele Standardmenüs finden Sie in der Unit *MenuIntf*. Zum Beispiel den Abschnitt **mnuTools**, der das Menü *Tools* aus dem IDE-Hauptmenü liefert. Es enthält einen Abschnitt **itmSecondaryTools**, das ist der empfohlene Abschnitt für "Third party tools".
49+
50+Das folgende Beispiel registriert einen neuen Menübefehl mit dem Namen 'MyTool', der Beschriftung 'Start my tool' und führt beim Klicken die Prozedur *StartMyTool* aus:
51+
52+``` pascal
53+procedure StartMyTool;
54+begin
55+ ...wird ausgeführt, wenn der Menüpunkt angeklickt wird...
56+end;
57+
58+procedure Register;
59+begin
60+ RegisterIDEMenuCommand(itmSecondaryTools, 'MyTool','Start my tool',nil,@StartMyTool);
61+end;
62+```
63+
64+Falls Sie statt der Prozedur eine Methode aufrufen wollen, dann verwenden Sie den **OnClickMethod** Parameter.
65+
66+Dieser Menüpunkt hat kein Tastenkürzel. Wenn Sie ein Tastenkürzel brauchen, dann erzeugen Sie einen **TIDECommand** und übergeben das Kürzel im **Command** Parameter. Zum Beispiel:
67+
68+``` pascal
69+uses ... IDECommands, MenuIntf;
70+...
71+var
72+ Key: TIDEShortCut;
73+ Cat: TIDECommandCategory;
74+ CmdMyTool: TIDECommand;
75+begin
76+ // register IDE shortcut and menu item
77+ Key := IDEShortCut(VK_UNKNOWN,[],VK_UNKNOWN,[]);
78+ Cat := IDECommandList.FindCategoryByName(CommandCategoryToolMenuName);
79+ CmdMyTool := RegisterIDECommand(Cat,'Start my tool', 'Starts my tool to do some stuff', Key, nil, @StartMyTool);
80+ RegisterIDEMenuCommand(itmSecondaryTools, 'MyTool', 'Start my tool', nil, nil, CmdMyTool);
81+end;
82+```
83+
84+# Konfigurationsdateien
85+
86+## Laden/Speichern von Einstellungen
87+
88+Alle Konfigurationsdateien der IDE werden in einem einzigen Verzeichnis als xml-Dateien gespeichert. Auch Packages können dort ihre eigenen Dateien ablegen. Das primäre Konfigurationsverzeichnis kann ermittelt werden mit:
89+
90+``` pascal
91+uses LazIDEIntf;
92+...
93+ Directory := LazarusIDE.GetPrimaryConfigPath;
94+```
95+
96+Packages erzeugen ihre eigenen xml-Dateien mit:
97+
98+``` pascal
99+uses
100+ ..., LCLProc, BaseIDEIntf, LazConfigStorage;
101+
102+const
103+ Version = 1;
104+var
105+ Config: TConfigStorage;
106+ SomeValue: String;
107+ SomeInteger: Integer;
108+ SomeBoolean: Boolean;
109+ FileVersion: LongInt;
110+begin
111+ SomeValue:='Default';
112+ SomeInteger:=3;
113+ SomeBoolean:=true;
114+
115+ // speichere die Einstellungen
116+ try
117+ Config:=GetIDEConfigStorage('mysettings.xml',false);
118+ try
119+ // store the version number so future extensions can handle old config files
120+ Config.SetDeleteValue('Path/To/The/Version',Version,0);
121+ // store string variable "SomeValue"
122+ // if SomeValue has the default value the entry is not stored,
123+ // so only the differences to the default are stored.
124+ // This way the xml is kept short and defaults may change in future.
125+ Config.SetDeleteValue('Path/To/Some/Value',SomeValue,'Default');
126+ Config.SetDeleteValue('Path/To/Some/Integer',SomeInteger,3);
127+ Config.SetDeleteValue('Path/To/Some/Boolean',SomeBoolean,true);
128+ // there are more overloads for SetDeleteValue, find out with Ctrl+Space
129+ finally
130+ Config.Free;
131+ end;
132+
133+ except
134+ on E: Exception do begin
135+ DebugLn(['Saving mysettings.xml failed: ',E.Message]);
136+ end;
137+ end;
138+
139+ // lade die Einstellungen
140+ try
141+ Config:=GetIDEConfigStorage('mysettings.xml',true);
142+ try
143+ // read the version of the config
144+ FileVersion:=Config.GetValue('Path/To/The/Version',0);
145+ // read a string variable "SomeValue". If the entry does not exist, use
146+ // the Default
147+ SomeValue:=Config.GetValue('Path/To/Some/Value','Default');
148+ SomeInteger:=Config.GetValue('Path/To/Some/Integer',3);
149+ SomeBoolean:=Config.GetValue('Path/To/Some/Boolean',true);
150+ finally
151+ Config.Free;
152+ end;
153+ except
154+ on E: Exception do begin
155+ DebugLn(['Loading mysettings.xml failed: ',E.Message]);
156+ end;
157+ end;
158+end;
159+```
160+
161+# Komponenten
162+
163+## Komponenten schreiben
164+
165+Sie können mit dem Lazarus Package-Editor eine neue, eigene Komponente erstellen. Sie erreichen den Editor über die Menüführung "Datei --\> Neu --\> Package, Standard Package". Es öffnet sich ein Fenster mit dem Datei- und Komponentenbaum Ihres Packages. Über die dort angezeigten Schaltflächen können Sie Ihr Package einrichten:
166+
167+- **Speichern:** Hier können Sie Ihre Komponente oder Ihr Package unter einen Namen Ihrer Wahl speichern.
168+- **Hinzufügen:** Hier erscheint ein Fenster mit mehreren Tabs. Die wichtisten im Überblick: Im Tab *Neue Datei* können Sie zum Beispiel Units und Formulardateien für Ihr Projekt erstellen. Eine bereits vorhandene Unit können Sie im Reiter *Neue Unit* einbinden. Wenn Sie Ihre Komponente auf eine bereits existierende Komponente aufbauen wollen, können Sie diese im Tab *Neue Komponente* auswählen.
169+- **Einstellungen:** In diesem Dialog können Sie neben der Beschreibung Ihrer Komponente und ihrer Versionierung auch den Package-Typ einstellen sowie Sprachregelungen treffen.
170+- **Installieren:** Wenn Ihre Komponente fertig erstellt ist, können Sie sie über diesen Knopf in die IDE einbinden.
171+- **Compilereinstellungen:** Hier lässt sich festlegen, mit welchen Optionen und Compiler-Argumenten Ihr Package kompiliert werden soll.
172+
173+**Hinweis**: Detailierte Informationen zum Package-Editor finden Sie [[IDE Window: Package Editor/de|hier.]]
174+
175+*Beispiel: Eine von TButton abgeleitete Komponente erstellen:*
176+
177+1. Öffnen Sie den Package-Editor wie oben geschrieben
178+2. Klicken Sie auf "Hinzufügen --\> Neue Komponente"
179+3. Wählen Sie als Basisklasse "TButton", und füllen die Felder wie folgt aus: Neuer Klassenname: TMeinButton, Palettenseite: Misc, Unit Dateiname: meinbutton.pas (diese Datei wird erstellt), Unit Name: MeinButton
180+4. Klicken Sie auf Ok - und schon können Sie in der Unit meinbutton.pas den TButton an Ihre Bedürfnisse anpassen.
181+
182+### Einer neuen Komponente ein Icon für die Komponentenpalette geben
183+
184+Zum Beispiel wollen wir TMyButton ein Icon geben. Erzeugen sie eine Bilddatei im Format .bmp, .xpm oder .png mit dem selben Namen wie die Komponentenklasse, z.B. *tmybutton.png* und speichern sie diese im Package-Quelltextverzeichnis. Das Bild kann mit einem beliebigen Grafikprogramm (z.B. Gimp) erzeugt werden und sollte nicht größer sein als 24x24 Pixel. Konvertieren Sie das Bild in eine .lrs Datei mit dem 'lazres' Werkzeug, das Sie im Verzeichnis 'lazarus/tools' finden:
185+
186+` ~/lazarus/tools/lazres mybutton.lrs tmybutton.png`
187+
188+Das erzeugt eine Pascal Include Datei, die im Initialisierungs-Abschnitt von mybutton.pas verwendet wird:
189+
190+` initialization`\
191+`   {$I mybutton.lrs}`
192+
193+Installieren Sie das Package.
194+
195+### Eine Komponente aus der Palette verstecken
196+
197+Package IDEIntf, unit componentreg:
198+
199+`IDEComponentPalette.FindComponent('TButton').Visible:=false;`
200+
201+## Komponenten-Editoren schreiben
202+
203+Ein Komponenten-Editor verarbeitet Dinge wie einen Doppelklick auf eine Komponente im Designer oder das Hinzufügen von Menüpunkten bei einem Rechtsklick auf eine Komponente. Einen Komponenten-Editor zu schreiben ist einfach. Siehe die Unit *componenteditors.pas* vom Package *IDEIntf* für zahlreiche Beispiele. Um beispielweise beim Doppelklick einen Editor anzuzeigen, siehe: TCheckListBoxComponentEditor.
204+
205+## Eigenschafts-Editoren schreiben
206+
207+Jeder Eigenschaftstyp (integer, string, TFont, ...) im Objektinspektor benötigt einen Eigenschafts-Editor. Wenn Ihre Komponente eine Eigenschaft 'Password' vom Typ *string* hat, können Sie einen Eigenschafts-Editor definieren für Ihre besondere Komponenten-Klasse, mit genau diesem Typ. Die Unit *propedits.pp* aus dem Package *IDEIntf* enthält viele der Standard-Eigenschafts-Editoren, die von der IDE selbst verwendet werden. Zum Beispiel ist der *TStringPropertyEditor* der vorgegebene Editor für alle Strings, während *TComponentNamePropertyEditor* spezieller ist und nur *TComponent.Name* bearbeitet.
208+
209+# Designer
210+
211+## Einen Designer-Mediator schreiben
212+
213+Der Standard-Designer erlaubt es, die Steuerelemente der LCL visuell zu bearbeiten, wo hingegen alle anderen nur als Symbole angezeigt werden. Um Steuerelemente (die nicht aus der LCL stammen) ebenfalls visuell bearbeiten zu können, sollten Sie einen **Designer-Mediator** erzeugen. Dieser kann dazu verwendet werden, Webseiten zu entwerfen, UML Diagramme oder andere Widgetsets wie [[fpGUI]]. Es gibt ein ausführliches Beispiel unter: in examples/designnonlcl/.
214+
215+- Installieren Sie das Beispielspackage examples/designnonlcl/notlcldesigner.lpk und starten Sie die IDE neu. Dadurch werden der Designer-Mediator für TMyWidget-Komponenten registriert und die neuen Komponenten TMyButton, TMyGroupBox zur Komponentenpalette hinzugefügt.
216+- Öffnen Sie das Beispielsprojekt examples/designnonlcl/project/NonLCL1.lpi.
217+- Öffnen Sie die unit1.pas und zeigen Sie das Formular im Designer an (mit F12). Sie sollten jetzt die Komponenten als rote Rechtecke dargestellt sehen, die Sie genau so wie LCL-Steuerelemente auswählen, verschieben oder in der Größe verändern können.
218+
219+## Einen neuen einzigartigen Komponentennamen erzeugen
220+
221+``` pascal
222+uses FormEditingIntf;
223+
224+...
225+
226+NewName:=FormEditingHook.CreateUniqueComponentName(AComponent);
227+
228+// Or if you need to create the name before creating the component:
229+
230+NewName:=FormEditingHook.CreateUniqueComponentName(ComponentClassName,OwnerComponent);
231+// ComponentClassName will be used as prefix, without a leading T.
232+// OwnerComponent is the new owner of the new component.
233+```
234+
235+## Eine Komponente im Designer/Objektinspektor auswählen
236+
237+``` pascal
238+uses propedits;
239+..
240+GlobalDesignHook.SelectOnlyThis(AComponent);
241+```
242+
243+# Ereignis-Handler
244+
245+Es gibt einige Ereignisse in der IDE, für die Plugins ihre eigenen Handler hinzufügen können.
246+
247+## Designerereignisse
248+
249+In propedits.pp gibt es ein "GlobalDesignHook" Objekt, das verschiedene Ereignisse zum Entwurf verwaltet. Jedes Ereignis ruft eine List von Handlern auf. Die Vorgabe-Handler werden von der IDE angefügt. Sie können eigene Handler mit den Methoden *AddHandlerXXX* und *RemoveHandlerXXX* anfügen. Diese werden aufgerufen vor den Vorgabe-Handlern.
250+
251+Beispiele:
252+
253+` Einfügen Ihres Handlers (das geschieht normalerweise im Konstruktor Ihres Objekts):`\
254+`   GlobalDesignHook.AddHandlerComponentAdded(@YourOnComponentAdded);`\
255+`  Entfernen Ihrer Handlers:`\
256+`   GlobalDesignHook.RemoveHandlerComponentAdded(@YourOnComponentAdded);`\
257+`  Sie können alle Handler auf einmal entfernen. Zum Beispiel, ist es eine gute Idee,`\
258+` diese Zeile im Destruktor des Objekts anzufügen:`\
259+`   GlobalDesignHook.RemoveAllHandlersForObject(Self);`
260+
261+Die Handler von GlobalDesignHook:
262+
263+` // lookup root`\
264+` ChangeLookupRoot`\
265+`   Called when the "LookupRoot" changed.`\
266+`   The "LookupRoot" is the owner object of the currently selected components.`\
267+`   Normally this is a TForm.`\
268+`  // methods`\
269+` CreateMethod`\
270+` GetMethodName`\
271+` GetMethods`\
272+` MethodExists`\
273+` RenameMethod`\
274+` ShowMethod`\
275+`   Called`\
276+` MethodFromAncestor`\
277+` ChainCall`\
278+`  // components`\
279+` GetComponent`\
280+` GetComponentName`\
281+` GetComponentNames`\
282+` GetRootClassName`\
283+` ComponentRenamed`\
284+`   Called when a component was renamed`\
285+` ComponentAdded`\
286+`   Called when a new component was added to the LookupRoot`\
287+` ComponentDeleting`\
288+`   Called before a component is freed.`\
289+` DeleteComponent`\
290+`   Called by the IDE to delete a component.`\
291+` GetSelectedComponents`\
292+`   Get the current selection of components.`\
293+`  // persistent objects`\
294+` GetObject`\
295+` GetObjectName`\
296+` GetObjectNames`\
297+`  // modifing`\
298+` Modified`\
299+` Revert`\
300+` RefreshPropertyValues`
301+
302+## Benachrichtigt werden, wenn ein Formular im Designer modifiziert wurde
303+
304+Jedes LCL-Formular hat einen Designer des Typs TIDesigner. Die IDE erzeugt Designer der Type TComponentEditorDesigner, die in der IDEIntf Unit componenteditors definiert ist. Ein Beispiel:
305+
306+``` pascal
307+procedure TYourAddOn.OnDesignerModified(Sender: TObject);
308+var
309+ IDEDesigner: TComponentEditorDesigner;
310+begin
311+ IDEDesigner:=TComponentEditorDesigner(Sender);
312+ ...
313+end;
314+
315+procedure TYourAddOn.ConnectDesignerForm(Form1: TCustomForm);
316+var
317+ IDEDesigner: TComponentEditorDesigner;
318+begin
319+ IDEDesigner:=TComponentEditorDesigner(Form1.Designer);
320+ IDEDesigner.AddHandlerModified(@OnDesignerModified);
321+end;
322+```
323+
324+## Projektereignisse
325+
326+Diese Ereignisse sind definiert in der Unit LazIDEIntf.
327+
328+- **LazarusIDE.AddHandlerOnProjectClose**: wird aufgerufen bevor ein Projekt geschlossen wird
329+- **LazarusIDE.AddHandlerOnProjectOpened**: wird aufgerufen nachdem das Projekt vollständig geöffnet wurde (wenn beispielsweise alle erforderlichen Packages geladen und die Units im Quelltext-Editor geöffnet wurden)
330+- **LazarusIDE.AddHandlerOnSavingAll**: wird aufgerufen bevor die IDE alles speichert
331+- **LazarusIDE.AddHandlerOnSavedAll**: wird aufgerufen nachdem die IDE alles gespeichert hat
332+- **LazarusIDE.AddHandlerOnProjectBuilding**: wird aufgerufen bevor die IDE das Projekt erstellt
333+- **LazarusIDE.AddHandlerOnProjectDependenciesCompiling**: wird aufgerufen bevor die IDE die Packageabhängigkeiten eines Projekts kompiliert
334+- **LazarusIDE.AddHandlerOnProjectDependenciesCompiled**: wird aufgerufen nachdem die IDE die Packageabhängigkeiten eines Projekts kompiliert hat
335+
336+## Andere IDE Ereignisse
337+
338+- **LazarusIDE.AddHandlerOnIDERestoreWindows**: wird aufgerufen, wenn die IDE ihre Fernster wiederherstellt (bevor das erste Projekt geöffnet wird)
339+- **LazarusIDE.AddHandlerOnIDEClose**: wird aufgerufen, wenn die IDE beendet wird (nach closequery, also keine Interaktivität mehr)
340+- **LazarusIDE.AddHandlerOnQuickSyntaxCheck**: wird aufgerufen, wenn der Menüpunkt oder das Tastenkürzel für die Schnelle Syntaxüberprüfung aussgeführt wird
341+
342+# Projekt
343+
344+## Aktuelles Projekt
345+
346+Das aktuelle Hauptprojekt erhalten Sie mit LazarusIDE.ActiveProject. (unit LazIDEIntf)
347+
348+## Alle Units des aktuellen Projekts
349+
350+Um alle Pascal-Units des aktuellen Hauptprojektes der IDE zu durchlaufen benutzen Sie zum Beispiel:
351+
352+``` pascal
353+uses LCLProc, FileUtil, LazIDEIntf, ProjectIntf;
354+
355+procedure ListProjectUnits;
356+var
357+ LazProject: TLazProject;
358+ i: Integer;
359+ LazFile: TLazProjectFile;
360+begin
361+ LazProject:=LazarusIDE.ActiveProject;
362+ if LazProject<>nil then
363+ for i:=0 to LazProject.FileCount-1 do
364+ begin
365+ LazFile:=LazProject.Files[i];
366+ if LazFile.IsPartOfProject
367+ and FilenameIsPascalUnit(LazFile.Filename)
368+ then
369+ debugln(LazFile.Filename);
370+ end;
371+end;
372+```
373+
374+## Die .lpr, .lpi und .lps Datei eines Projekts
375+
376+``` pascal
377+uses LCLProc, FileUtil, ProjectIntf, LazIDEIntf;
378+var
379+ LazProject: TLazProject;
380+begin
381+ LazProject:=LazarusIDE.ActiveProject;
382+ // jedes Projekt hat eine .lpi Datei:
383+ DebugLn(['Project'' lpi file: ',LazProject.ProjectInfoFile]);
384+
385+ // if the project session information is stored in a separate .lps file:
386+ if LazProject.SessionStorage<>pssNone then
387+ DebugLn(['Project'' lps file: ',LazProject.ProjectSessionFile]);
388+
389+ // If the project has a .lpr file it is the main source file:
390+ if (LazProject.MainFile<>nil)
391+ and (CompareFileExt(LazProject.MainFile.Filename,'lpr')=0) then
392+ DebugLn(['Project has lpr file: ',LazProject.MainFile.Filename]);
393+end;
394+```
395+
396+## Der Name der ausführbaren Ziel-Datei eines Projekts
397+
398+Es gibt ein Makro \$(TargetFile), das in Pfaden und externen Werkzeugen verwendet werden kann. Beispiel:
399+
400+``` pascal
401+uses MacroIntf;
402+
403+function MyGetProjectTargetFile: string;
404+begin
405+ Result:='$(TargetFile)';
406+ if not IDEMacros.SubstituteMacros(Result) then
407+ raise Exception.Create('unable to retrieve target file of project');
408+end;
409+```
410+
411+Für weitere Makros siehe: [[IDE Macros in paths and filenames/de|IDE Makros in Pfaden und Dateinamen]].
412+
413+## Hinzufügen Ihres eigenen Projekttyps
414+
415+Sie können Menüpunkte zum Dialog 'Neu ...' hinzufügen:
416+
417+- Siehe die Unit ProjectIntf aus dem Package IDEIntf.
418+- Siehe die [[Project Templates]]
419+
420+## Hinzufügen Ihres eigenen Dateityps
421+
422+Sie können Einträge hinzufügen zum Dialog 'Neu ...':
423+
424+- Siehe die Unit ProjectIntf aus dem Package IDEIntf.
425+- Wählen Sie eine Basisklasse TFileDescPascalUnit für normale Units oder TFileDescPascalUnitWithResource für ein neues Formular/Datenmodul.
426+
427+### Hinzufügen eines neuen Dateityps
428+
429+Dieses Beispiel entstammt der ide/mainintf.pas Datei und registriert eine einfache Textdatei:
430+
431+``` pascal
432+uses ProjectIntf;
433+...
434+ { TFileDescText }
435+
436+ TFileDescMyText = class(TProjectFileDescriptor)
437+ public
438+ constructor Create; override;
439+ function GetLocalizedName: string; override;
440+ function GetLocalizedDescription: string; override;
441+ end;
442+...
443+
444+procedure Register;
445+
446+implementation
447+
448+procedure Register;
449+begin
450+ RegisterProjectFileDescriptor(TFileDescMyText.Create,FileDescGroupName);
451+end;
452+
453+{ TFileDescMyText }
454+
455+constructor TFileDescMyText.Create;
456+begin
457+ inherited Create;
458+ Name:='MyText'; // do not translate this
459+ DefaultFilename:='text.txt';
460+ AddToProject:=false;
461+end;
462+
463+function TFileDescText.GetLocalizedName: string;
464+begin
465+ Result:='My Text'; // replace this with a resourcestring
466+end;
467+
468+function TFileDescText.GetLocalizedDescription: string;
469+begin
470+ Result:='An empty text file';
471+end;
472+```
473+
474+### Hinzufügen eines neuen Formulartyps
475+
476+Diese Beispiel ist aus 'ide/mainintf.pas' und registriert das normale Formular:
477+
478+``` pascal
479+uses ProjectIntf;
480+
481+...
482+ TFileDescPascalUnitWithMyForm = class(TFileDescPascalUnitWithResource)
483+ public
484+ constructor Create; override;
485+ function GetInterfaceUsesSection: string; override;
486+ function GetLocalizedName: string; override;
487+ function GetLocalizedDescription: string; override;
488+ end;
489+...
490+
491+procedure Register;
492+
493+implementation
494+
495+procedure Register;
496+begin
497+ RegisterProjectFileDescriptor(TFileDescPascalUnitWithMyForm.Create,FileDescGroupName);
498+end;
499+
500+{ TFileDescPascalUnitWithMyForm }
501+
502+constructor TFileDescPascalUnitWithMyForm.Create;
503+begin
504+ inherited Create;
505+ Name:='MyForm'; // do not translate this
506+ ResourceClass:=TMyForm;
507+ UseCreateFormStatements:=true;
508+end;
509+
510+function TFileDescPascalUnitWithMyForm.GetInterfaceUsesSection: string;
511+begin
512+ Result:='Classes, SysUtils, MyWidgetSet';
513+end;
514+
515+function TFileDescPascalUnitWithForm.GetLocalizedName: string;
516+begin
517+ Result:='MyForm'; // replace this with a resourcestring
518+end;
519+
520+function TFileDescPascalUnitWithForm.GetLocalizedDescription: string;
521+begin
522+ Result:='Create a new MyForm from example package NotLCLDesigner';
523+end;
524+```
525+
526+# Packages
527+
528+## Suche in allen Packages
529+
530+Durchsuche alle Packages die in der IDE geladen sind (seit Version 0.9.29):
531+
532+``` pascal
533+uses PackageIntf;
534+...
535+for i:=0 to PackageEditingInterface.GetPackageCount-1 do
536+ writeln(PackageEditingInterface.GetPackages(i).Name);
537+```
538+
539+## Suche ein Package mit einem bestimmten Namen
540+
541+``` pascal
542+uses PackageIntf;
543+...
544+var
545+ Pkg: TIDEPackage;
546+begin
547+ Pkg:=PackageEditingInterface.FindPackageWithName('LCL');
548+ if Pkg<>nil then
549+ ...
550+end;
551+```
552+
553+Anmerkung: 'FindPackageWithName' öffnet nicht den Package-Editor. Benutzen Sie dazu 'DoOpenPackageWithName'.
554+
555+## Installieren von Packages
556+
557+**Anmerkung**: Installieren Sie nur Packages mit IDE-Plugins. Andere Packages zu installieren, kann die IDE instabil machen.
558+
559+``` pascal
560+uses PackageIntf, contnrs;
561+
562+ PkgList:=TObjectList.create(true);
563+ try
564+ Pkg:=TLazPackageID.Create;
565+ Pkg.Name:='Cody';
566+ PkgList.Add(Pkg);
567+ // überprüft, ob die IDE die Datei 'cody.lpk' und alle Abhängigkeiten finden kann
568+ // Die IDE gibt einige Warnungen/Bestätigungen aus, falls ihr irgendetwas seltsam vorkommt.
569+ if not PackageEditingInterface.CheckInstallPackageList(PkgList,[]) then
570+ exit;
571+ // in diesem Beispiel haben wir bereits überprüft, deshalb Warnungen überspringen
572+ // und die IDE neu erstellen
573+ if PackageEditingInterface.InstallPackages(PkgList,[piiifSkipChecks,piiifRebuildIDE])<>mrOK then
574+ exit;
575+ finally
576+ PkgList.Free;
577+ end;
578+```
579+
580+# Fenster
581+
582+Grundsätzlich gibt es vier Typen von IDE Fenstern:
583+
584+- die IDE Hauptleiste ist in Application.MainForm. Sie ist immer präsent.
585+- schwebende/andockbare Fenster (wie die Quelltext-Editoren, der Objektinspektor und die Meldungen)
586+- die modalen Formulare, wie der Suchen-Dialog, Einstellungen-Dialog und Rückfragen.
587+- Hints und Vervollständigungs-Formulare
588+
589+## Hinzufügen eines neuen andockbaren IDE-Fensters
590+
591+Was ist ein andockbares IDE-Fenster: Fenster wie der Quelltext-Editor oder der Objektinspektor sind schwebende Fenster, die angedockt werden können, wenn das Package 'docking' installiert ist. Sein Status, seine Position und Größe werden gespeichert und beim nächsten Start der IDE wieder abgerufen. Um ein Fenster wiederherstellen zu können, braucht die IDE einen Creator wie er in der Unit **IDEWindowIntf** des Packages 'IDEIntf' definiert ist. Jedes andockbare Fenster benötigt einen einzigartigen Namen. Verwenden Sie keine allgemeinen Namen wie 'FileBrowser' weil dies sehr leicht zu Konflikten mit anderen Packages führen kann. Und verwenden Sie keine Kurznamen wie 'XYZ', weil der Creator verantwortlich ist für alle Formulare, die mit diesem Namen beginnen.
592+
593+### Wie registriert man ein andockbares IDE-Fenster
594+
595+Vergessen Sie nicht, einen langen, uniquen Namen zu verwenden, der ein gültiger Pascal-Bezeichner ist. Ihr Fenster kann einen beliebigen Titel haben.
596+
597+``` pascal
598+uses SysUtils, IDEWindowIntf;
599+...
600+var MyIDEWindow: TMyIDEWindow = nil;
601+
602+procedure CreateMyIDEWindow(Sender: TObject; aFormName: string; var AForm: TCustomForm; DoDisableAutoSizing: boolean);
603+begin
604+ // check the name
605+ if CompareText(aFormName,MyIDEWindowName)<>0 then exit;
606+ // create the form if not already done and disable autosizing
607+ IDEWindowCreators.CreateForm(MyIDEWindow,TMyIDEWindowm,DoDisableAutosizing,Application);
608+ ... init the window ...
609+ AForm:=MyIDEWindow;
610+end;
611+
612+procedure Register;
613+begin
614+ IDEWindowCreators.Add('MyIDEWindow',@CreateMyIDEWindow,nil,'100','50%','+300','+20%');
615+ // the default boundsrect of the form is:
616+ // Left=100, Top=50% of Screen.Height, Width=300, Height=20% of Screen.Height
617+ // when the IDE needs an instance of this window it calls the procedure CreateMyIDEWindow.
618+end;
619+```
620+
621+### Anzeigen eines IDE-Fensters
622+
623+**Benutzen Sie nicht Show**. Nehmen Sie stattdessen:
624+
625+``` pascal
626+IDEWindowCreators.ShowForm(MyIDEWindow,false);
627+```
628+
629+Das wird auch mit Docking funktionieren. Das Docking-System wird das Formular in eine Docking-Site einschließen. Der Parameter 'BringToFront' befiehlt dem Docking-System, dieses Formular und all seine Eltern-Sites sichtbar zu machen und die Site der obersten Ebene in den Vordergrund zu bringen.
630+
631+### Anmerkungen über IDEWindowCreators und SimpleLayoutStorage
632+
633+Das IDEWindowCreators.SimpleLayoutStorage speichert einfach das BoundsRect und den WindowState von allen Formularen, die einmal geöffnet wurden. Es stellt ein Fallback dar, falls kein Dockmaster installiert ist. Es speichert des Zustand sogar wenn ein DockMaster installiert ist, sodass auch beim Deinstallieren des Dockmasters die Formulargrößen wiederhergestellt werden können.
634+
635+Die IDEWindowCreators werden bei allen andockbaren Formularen eingesetzt, um sich selbst zu registrieren und die Formulare anzuzeigen. Beim Anzeigen eines Formulars überprüft der Creator ob ein IDEDockMaster installiert ist und überträgt ihm die Aufgabe des Anzeigens. Ist kein IDEDockMaster installiert wird das Formular einfach angezeigt. Der IDEDockMaster kann die Informationen in den IDEWindowCreators benutzen, um benannte Formulare zu erzeugen und um festzustellen, wo ein Formular beim ersten Anzeigen zu platzieren ist. Für weitere Details siehe die Packages **AnchorDockingDsgn** und **EasyDockMgDsgn**.
636+
637+# CodeTools in der IDE
638+
639+Die CodeTools sind ein Package das eine große Anzahl von Funktionen zum Parsen, Untersuchen und Ändern von Pascal-Quelltexten zur Verfügung stellt, daneben auch einige grundlegende Funktionen für andere Sprachen. Sie können sie auch ohne die IDE einsetzen. Es wird empfohlen, dass Sie zuerst über die CodeTools im Allgemeinen nachlesen, bevor Sie sie in der IDE benutzen: [[Codetools/de|CodeTools (deutsch)]].
640+
641+Bevor Sie irgendeine der Codetools-Funktionen in der IDE aufrufen, sollten Sie die letzten Änderungen im Quelltexteditor in den Codetools-Puffern speichern:
642+
643+``` pascal
644+uses LazIDEIntf;
645+...
646+ // save changes in source editor to codetools
647+ LazarusIDE.SaveSourceEditorChangesToCodeCache(-1); // -1: commit all source editors
648+```
649+
650+## Hinzufügen einer resource Direktive zu einer Datei
651+
652+Dies fügt eine {\$R example.res} Direktive zu einer Pascal Unit hinzu:
653+
654+``` pascal
655+procedure AddResourceDirectiveToPascalSource(const Filename: string);
656+var
657+ ExpandedFilename: String;
658+ CodeBuf: TCodeBuffer;
659+begin
660+ // make sure the filename is trimmed and contains a full path
661+ ExpandedFilename:=CleanAndExpandFilename(Filename);
662+
663+ // save changes in source editor to codetools
664+ LazarusIDE.SaveSourceEditorChangesToCodeCache(-1);
665+
666+ // die Datei laden
667+ CodeBuf:=CodeToolBoss.LoadFile(ExpandedFilename,true,false);
668+
669+ // die resource Direktive hinzufügen
670+ if not CodeToolBoss.AddResourceDirective(CodeBuf,'example.res') then
671+ LazarusIDE.DoJumpToCodeToolBossError;
672+end;
673+```
674+
675+Die Codetools stellen auch Funktionen wie FindResourceDirective und RemoveDirective zur Verfügung.
676+
677+## Die Suchpfade für Units und Include-Dateien ermitteln
678+
679+In der IDE gibt es viele unterschiedliche Suchpfade von Projekten, Packages, dem FPC und Lazarus Verzeichnis und es gibt viele Arten von Pfaden: vor und nach dem Auflösen von Makros, mit oder ohne geerbte Suchpfade, als relative oder absolute Pfade. Alle Dateien in einem Verzeichnis teilen sich den selben Bestand an Suchpfaden. Sie erhalten die Suchpfade für jedes Verzeichnis voll aufgelöst durch eine Abfrage der Codetools:
680+
681+``` pascal
682+uses CodeToolManager;
683+...
684+
685+Dir:=''; // das leere Verzeichnis ist für neue Dateien und hat die selben Einstellungen wie das Projektverzeichnis
686+
687+// ermittelt die Suchpfade für Include-Dateien:
688+Path:=CodeToolBoss.GetIncludePathForDirectory(Dir);
689+
690+// ermittelt die Suchpfade für Units:
691+// Dieser Suchpfad wird an den Compiler übergeben.
692+// Er enthält die Package-Ausgabe-Verzeichnisse, aber nicht die Package-Quell-Verzeichnisse.
693+Path:=CodeToolBoss.GetUnitPathForDirectory(Dir);
694+
695+// zusätzliche Unit-Suchpfade nur für die IDE können auftreten (werden nicht an den Compiler übergeben)
696+Path:=CodeToolBoss.GetSrcPathForDirectory(Dir);
697+
698+// der vollständige Suchpfad enthält auch alle Package-Quell-Pfade für Units:
699+Path:=CodeToolBoss.GetCompleteSrcPathForDirectory(Dir);
700+```
701+
702+# Quelltext-Editor
703+
704+## Aktiver Quelltext-Editor
705+
706+``` pascal
707+uses SrcEditorIntf;
708+...
709+Editor:=SourceEditorManagerIntf.ActiveEditor;
710+if Editor=nil then exit;
711+Filename:=Editor.FileName;
712+ScreenPos:=Editor.CursorScreenXY;
713+TextPos:=Editor.CursorTextXY;
714+```
715+
716+# SynEdit
717+
718+## Die Einstellungen für einen TSynEdit holen
719+
720+Wenn Sie einen TSynEdit in einem Dialog haben und Sie wollen die selbe Schriftart und die selben Einstellungen wie im Quelltext-Editor verwenden::
721+
722+``` pascal
723+uses SrcEditorIntf;
724+...
725+SourceEditorManagerIntf.GetEditorControlSettings(ASynEdit);
726+```
727+
728+## Die Einstellungen für einen SynEdit-Highlighter holen
729+
730+Wenn Sie einen Dialog haben, der einen TSynEdit mit einem Highlighter enthält, können Sie die selben Farben wie der Highlighter des Quelltext-Editors für diese Sprache verwenden:
731+
732+``` pascal
733+uses SrcEditorIntf;
734+...
735+SourceEditorManagerIntf.GetHighlighterSettings(ASynHighlighter);
736+```
737+
738+Siehe für ein Beispiel auch: TSQLStringsPropertyEditorDlg.Create in der Unit [SQLStringsPropertyEditorDlg](http://svn.freepascal.org/svn/lazarus/trunk/components/sqldb/sqlstringspropertyeditordlg.pas).
739+
740+# Hilfe
741+
742+## Hilfe für die Quellen hinzufügen
743+
744+Erzeugen sie zuerst eine THelpDatabase:
745+
746+``` pascal
747+HelpDB := TFPDocHTMLHelpDatabase(
748+ HelpDatabases.CreateHelpDatabase('EinNameIhrerWahlFürDieDatenbank',
749+ TFPDocHTMLHelpDatabase,true));
750+ HelpDB.DefaultBaseURL := 'http://ihre.hilfe.org/';
751+
752+ FPDocNode := THelpNode.CreateURL(HelpDB,
753+ 'Package1 - A new package',
754+ 'file://index.html');
755+ HelpDB.TOCNode := THelpNode.Create(HelpDB,FPDocNode);// einmal als Inhaltsverzeichnis
756+ DirectoryItem := THelpDBISourceDirectory.Create(FPDocNode,'$(PkgDir)/lcl',
757+ '*.pp;*.pas',false);// und einmal als normale Seite
758+ HelpDB.RegisterItem(DirectoryItem);
759+```
760+
761+## Zeilen zum Nachrichtenfenster hinzufügen
762+
763+``` pascal
764+unit IDEMsgIntf;
765+...
766+var Dir: String;
767+begin
768+ Dir:=GetCurrentDir;
769+ IDEMessagesWindow.BeginBlock;
770+ IDEMessagesWindow.AddMsg('unit1.pas(30,4) Error: Identifier not found "a"',Dir,0);
771+ IDEMessagesWindow.EndBlock;
772+end;
773+```
774+
775+## Überblick über die verschiedenen Elemente der Hilfe
776+
777+[[Creating IDE Help/de|Hilfe für die IDE erzeugen]]
778+
779+---
780+*From the Free Pascal wiki, page "Extending the IDE/de", 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