Extending the IDE/de
│
Deutsch (de) │
English (en) │
español (es) │
français (fr) │
日本語 (ja) │
русский (ru) │
slovenčina (sk) │
中文(中国大陆) (zh_CN) │
Erweitern der IDE
Überblick
Die IDE unterstützt verschiedene Erweiterungen:
- Komponenten
- Komponenten werden in der Palette installiert. Z.B. TButton erzeugt Buttons.
- Komponenten-Editoren
- 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.
- Eigenschafts-Editoren
- Stellen die Editierfähigkeiten im Objektinspektor zur Verfügung.
- Experten
- Das sind alle anderen Typen von Editoren. Sie registrieren neue Menüpunkte, Tastenkürzel oder erweitern andere Merkmale der IDE.
Es gibt 2 Möglichkeiten, Ihre eigenen Plugins in Lazarus zu integrieren:
- Erstellen Sie ein Package, installieren Sie es und registrieren Sie das Plugin mit der Prozedur 'Register' in einer Unit.
- Erweitern Sie den Lazarus Code und senden Sie Ihr SVN diff an die Lazarus-Mailing-Liste.
Menüpunkte
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.
Einen Menüpunkt hinzufügen
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:
function RegisterIDEMenuCommand(Parent: TIDEMenuSection;
const Name, Caption: string;
const OnClickMethod: TNotifyEvent = nil;
const OnClickProc: TNotifyProcedure = nil;
const Command: TIDECommand = nil;
const ResourceName: String = ''
): TIDEMenuCommand; overload;
function RegisterIDEMenuCommand(const Path, Name, Caption: string;
const OnClickMethod: TNotifyEvent = nil;
const OnClickProc: TNotifyProcedure = nil;
const Command: TIDECommand = nil;
const ResourceName: String = ''
): TIDEMenuCommand; overload;
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".
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:
procedure StartMyTool;
begin
...wird ausgeführt, wenn der Menüpunkt angeklickt wird...
end;
procedure Register;
begin
RegisterIDEMenuCommand(itmSecondaryTools, 'MyTool','Start my tool',nil,@StartMyTool);
end;
Falls Sie statt der Prozedur eine Methode aufrufen wollen, dann verwenden Sie den OnClickMethod Parameter.
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:
uses ... IDECommands, MenuIntf;
...
var
Key: TIDEShortCut;
Cat: TIDECommandCategory;
CmdMyTool: TIDECommand;
begin
// register IDE shortcut and menu item
Key := IDEShortCut(VK_UNKNOWN,[],VK_UNKNOWN,[]);
Cat := IDECommandList.FindCategoryByName(CommandCategoryToolMenuName);
CmdMyTool := RegisterIDECommand(Cat,'Start my tool', 'Starts my tool to do some stuff', Key, nil, @StartMyTool);
RegisterIDEMenuCommand(itmSecondaryTools, 'MyTool', 'Start my tool', nil, nil, CmdMyTool);
end;
Konfigurationsdateien
Laden/Speichern von Einstellungen
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:
uses LazIDEIntf;
...
Directory := LazarusIDE.GetPrimaryConfigPath;
Packages erzeugen ihre eigenen xml-Dateien mit:
uses
..., LCLProc, BaseIDEIntf, LazConfigStorage;
const
Version = 1;
var
Config: TConfigStorage;
SomeValue: String;
SomeInteger: Integer;
SomeBoolean: Boolean;
FileVersion: LongInt;
begin
SomeValue:='Default';
SomeInteger:=3;
SomeBoolean:=true;
// speichere die Einstellungen
try
Config:=GetIDEConfigStorage('mysettings.xml',false);
try
// store the version number so future extensions can handle old config files
Config.SetDeleteValue('Path/To/The/Version',Version,0);
// store string variable "SomeValue"
// if SomeValue has the default value the entry is not stored,
// so only the differences to the default are stored.
// This way the xml is kept short and defaults may change in future.
Config.SetDeleteValue('Path/To/Some/Value',SomeValue,'Default');
Config.SetDeleteValue('Path/To/Some/Integer',SomeInteger,3);
Config.SetDeleteValue('Path/To/Some/Boolean',SomeBoolean,true);
// there are more overloads for SetDeleteValue, find out with Ctrl+Space
finally
Config.Free;
end;
except
on E: Exception do begin
DebugLn(['Saving mysettings.xml failed: ',E.Message]);
end;
end;
// lade die Einstellungen
try
Config:=GetIDEConfigStorage('mysettings.xml',true);
try
// read the version of the config
FileVersion:=Config.GetValue('Path/To/The/Version',0);
// read a string variable "SomeValue". If the entry does not exist, use
// the Default
SomeValue:=Config.GetValue('Path/To/Some/Value','Default');
SomeInteger:=Config.GetValue('Path/To/Some/Integer',3);
SomeBoolean:=Config.GetValue('Path/To/Some/Boolean',true);
finally
Config.Free;
end;
except
on E: Exception do begin
DebugLn(['Loading mysettings.xml failed: ',E.Message]);
end;
end;
end;
Komponenten
Komponenten schreiben
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:
- Speichern: Hier können Sie Ihre Komponente oder Ihr Package unter einen Namen Ihrer Wahl speichern.
- 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.
- Einstellungen: In diesem Dialog können Sie neben der Beschreibung Ihrer Komponente und ihrer Versionierung auch den Package-Typ einstellen sowie Sprachregelungen treffen.
- Installieren: Wenn Ihre Komponente fertig erstellt ist, können Sie sie über diesen Knopf in die IDE einbinden.
- Compilereinstellungen: Hier lässt sich festlegen, mit welchen Optionen und Compiler-Argumenten Ihr Package kompiliert werden soll.
Hinweis: Detailierte Informationen zum Package-Editor finden Sie hier.
Beispiel: Eine von TButton abgeleitete Komponente erstellen:
- Öffnen Sie den Package-Editor wie oben geschrieben
- Klicken Sie auf "Hinzufügen --> Neue Komponente"
- 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
- Klicken Sie auf Ok - und schon können Sie in der Unit meinbutton.pas den TButton an Ihre Bedürfnisse anpassen.
Einer neuen Komponente ein Icon für die Komponentenpalette geben
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:
~/lazarus/tools/lazres mybutton.lrs tmybutton.png
Das erzeugt eine Pascal Include Datei, die im Initialisierungs-Abschnitt von mybutton.pas verwendet wird:
initialization {$I mybutton.lrs}
Installieren Sie das Package.
Eine Komponente aus der Palette verstecken
Package IDEIntf, unit componentreg:
IDEComponentPalette.FindComponent('TButton').Visible:=false;
Komponenten-Editoren schreiben
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.
Eigenschafts-Editoren schreiben
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.
Designer
Einen Designer-Mediator schreiben
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/.
- 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.
- Öffnen Sie das Beispielsprojekt examples/designnonlcl/project/NonLCL1.lpi.
- Ö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.
Einen neuen einzigartigen Komponentennamen erzeugen
uses FormEditingIntf;
...
NewName:=FormEditingHook.CreateUniqueComponentName(AComponent);
// Or if you need to create the name before creating the component:
NewName:=FormEditingHook.CreateUniqueComponentName(ComponentClassName,OwnerComponent);
// ComponentClassName will be used as prefix, without a leading T.
// OwnerComponent is the new owner of the new component.
Eine Komponente im Designer/Objektinspektor auswählen
uses propedits;
..
GlobalDesignHook.SelectOnlyThis(AComponent);
Ereignis-Handler
Es gibt einige Ereignisse in der IDE, für die Plugins ihre eigenen Handler hinzufügen können.
Designerereignisse
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.
Beispiele:
Einfügen Ihres Handlers (das geschieht normalerweise im Konstruktor Ihres Objekts): GlobalDesignHook.AddHandlerComponentAdded(@YourOnComponentAdded);
Entfernen Ihrer Handlers: GlobalDesignHook.RemoveHandlerComponentAdded(@YourOnComponentAdded);
Sie können alle Handler auf einmal entfernen. Zum Beispiel, ist es eine gute Idee, diese Zeile im Destruktor des Objekts anzufügen: GlobalDesignHook.RemoveAllHandlersForObject(Self);
Die Handler von GlobalDesignHook:
// lookup root ChangeLookupRoot Called when the "LookupRoot" changed. The "LookupRoot" is the owner object of the currently selected components. Normally this is a TForm.
// methods CreateMethod GetMethodName GetMethods MethodExists RenameMethod ShowMethod Called MethodFromAncestor ChainCall
// components GetComponent GetComponentName GetComponentNames GetRootClassName ComponentRenamed Called when a component was renamed ComponentAdded Called when a new component was added to the LookupRoot ComponentDeleting Called before a component is freed. DeleteComponent Called by the IDE to delete a component. GetSelectedComponents Get the current selection of components.
// persistent objects GetObject GetObjectName GetObjectNames
// modifing Modified Revert RefreshPropertyValues
Benachrichtigt werden, wenn ein Formular im Designer modifiziert wurde
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:
procedure TYourAddOn.OnDesignerModified(Sender: TObject);
var
IDEDesigner: TComponentEditorDesigner;
begin
IDEDesigner:=TComponentEditorDesigner(Sender);
...
end;
procedure TYourAddOn.ConnectDesignerForm(Form1: TCustomForm);
var
IDEDesigner: TComponentEditorDesigner;
begin
IDEDesigner:=TComponentEditorDesigner(Form1.Designer);
IDEDesigner.AddHandlerModified(@OnDesignerModified);
end;
Projektereignisse
Diese Ereignisse sind definiert in der Unit LazIDEIntf.
- LazarusIDE.AddHandlerOnProjectClose: wird aufgerufen bevor ein Projekt geschlossen wird
- 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)
- LazarusIDE.AddHandlerOnSavingAll: wird aufgerufen bevor die IDE alles speichert
- LazarusIDE.AddHandlerOnSavedAll: wird aufgerufen nachdem die IDE alles gespeichert hat
- LazarusIDE.AddHandlerOnProjectBuilding: wird aufgerufen bevor die IDE das Projekt erstellt
- LazarusIDE.AddHandlerOnProjectDependenciesCompiling: wird aufgerufen bevor die IDE die Packageabhängigkeiten eines Projekts kompiliert
- LazarusIDE.AddHandlerOnProjectDependenciesCompiled: wird aufgerufen nachdem die IDE die Packageabhängigkeiten eines Projekts kompiliert hat
Andere IDE Ereignisse
- LazarusIDE.AddHandlerOnIDERestoreWindows: wird aufgerufen, wenn die IDE ihre Fernster wiederherstellt (bevor das erste Projekt geöffnet wird)
- LazarusIDE.AddHandlerOnIDEClose: wird aufgerufen, wenn die IDE beendet wird (nach closequery, also keine Interaktivität mehr)
- LazarusIDE.AddHandlerOnQuickSyntaxCheck: wird aufgerufen, wenn der Menüpunkt oder das Tastenkürzel für die Schnelle Syntaxüberprüfung aussgeführt wird
Projekt
Aktuelles Projekt
Das aktuelle Hauptprojekt erhalten Sie mit LazarusIDE.ActiveProject. (unit LazIDEIntf)
Alle Units des aktuellen Projekts
Um alle Pascal-Units des aktuellen Hauptprojektes der IDE zu durchlaufen benutzen Sie zum Beispiel:
uses LCLProc, FileUtil, LazIDEIntf, ProjectIntf;
procedure ListProjectUnits;
var
LazProject: TLazProject;
i: Integer;
LazFile: TLazProjectFile;
begin
LazProject:=LazarusIDE.ActiveProject;
if LazProject<>nil then
for i:=0 to LazProject.FileCount-1 do
begin
LazFile:=LazProject.Files[i];
if LazFile.IsPartOfProject
and FilenameIsPascalUnit(LazFile.Filename)
then
debugln(LazFile.Filename);
end;
end;
Die .lpr, .lpi und .lps Datei eines Projekts
uses LCLProc, FileUtil, ProjectIntf, LazIDEIntf;
var
LazProject: TLazProject;
begin
LazProject:=LazarusIDE.ActiveProject;
// jedes Projekt hat eine .lpi Datei:
DebugLn(['Project'' lpi file: ',LazProject.ProjectInfoFile]);
// if the project session information is stored in a separate .lps file:
if LazProject.SessionStorage<>pssNone then
DebugLn(['Project'' lps file: ',LazProject.ProjectSessionFile]);
// If the project has a .lpr file it is the main source file:
if (LazProject.MainFile<>nil)
and (CompareFileExt(LazProject.MainFile.Filename,'lpr')=0) then
DebugLn(['Project has lpr file: ',LazProject.MainFile.Filename]);
end;
Der Name der ausführbaren Ziel-Datei eines Projekts
Es gibt ein Makro $(TargetFile), das in Pfaden und externen Werkzeugen verwendet werden kann. Beispiel:
uses MacroIntf;
function MyGetProjectTargetFile: string;
begin
Result:='$(TargetFile)';
if not IDEMacros.SubstituteMacros(Result) then
raise Exception.Create('unable to retrieve target file of project');
end;
Für weitere Makros siehe: IDE Makros in Pfaden und Dateinamen.
Hinzufügen Ihres eigenen Projekttyps
Sie können Menüpunkte zum Dialog 'Neu ...' hinzufügen:
- Siehe die Unit ProjectIntf aus dem Package IDEIntf.
- Siehe die Project Templates
Hinzufügen Ihres eigenen Dateityps
Sie können Einträge hinzufügen zum Dialog 'Neu ...':
- Siehe die Unit ProjectIntf aus dem Package IDEIntf.
- Wählen Sie eine Basisklasse TFileDescPascalUnit für normale Units oder TFileDescPascalUnitWithResource für ein neues Formular/Datenmodul.
Hinzufügen eines neuen Dateityps
Dieses Beispiel entstammt der ide/mainintf.pas Datei und registriert eine einfache Textdatei:
uses ProjectIntf;
...
{ TFileDescText }
TFileDescMyText = class(TProjectFileDescriptor)
public
constructor Create; override;
function GetLocalizedName: string; override;
function GetLocalizedDescription: string; override;
end;
...
procedure Register;
implementation
procedure Register;
begin
RegisterProjectFileDescriptor(TFileDescMyText.Create,FileDescGroupName);
end;
{ TFileDescMyText }
constructor TFileDescMyText.Create;
begin
inherited Create;
Name:='MyText'; // do not translate this
DefaultFilename:='text.txt';
AddToProject:=false;
end;
function TFileDescText.GetLocalizedName: string;
begin
Result:='My Text'; // replace this with a resourcestring
end;
function TFileDescText.GetLocalizedDescription: string;
begin
Result:='An empty text file';
end;
Hinzufügen eines neuen Formulartyps
Diese Beispiel ist aus 'ide/mainintf.pas' und registriert das normale Formular:
uses ProjectIntf;
...
TFileDescPascalUnitWithMyForm = class(TFileDescPascalUnitWithResource)
public
constructor Create; override;
function GetInterfaceUsesSection: string; override;
function GetLocalizedName: string; override;
function GetLocalizedDescription: string; override;
end;
...
procedure Register;
implementation
procedure Register;
begin
RegisterProjectFileDescriptor(TFileDescPascalUnitWithMyForm.Create,FileDescGroupName);
end;
{ TFileDescPascalUnitWithMyForm }
constructor TFileDescPascalUnitWithMyForm.Create;
begin
inherited Create;
Name:='MyForm'; // do not translate this
ResourceClass:=TMyForm;
UseCreateFormStatements:=true;
end;
function TFileDescPascalUnitWithMyForm.GetInterfaceUsesSection: string;
begin
Result:='Classes, SysUtils, MyWidgetSet';
end;
function TFileDescPascalUnitWithForm.GetLocalizedName: string;
begin
Result:='MyForm'; // replace this with a resourcestring
end;
function TFileDescPascalUnitWithForm.GetLocalizedDescription: string;
begin
Result:='Create a new MyForm from example package NotLCLDesigner';
end;
Packages
Suche in allen Packages
Durchsuche alle Packages die in der IDE geladen sind (seit Version 0.9.29):
uses PackageIntf;
...
for i:=0 to PackageEditingInterface.GetPackageCount-1 do
writeln(PackageEditingInterface.GetPackages(i).Name);
Suche ein Package mit einem bestimmten Namen
uses PackageIntf;
...
var
Pkg: TIDEPackage;
begin
Pkg:=PackageEditingInterface.FindPackageWithName('LCL');
if Pkg<>nil then
...
end;
Anmerkung: 'FindPackageWithName' öffnet nicht den Package-Editor. Benutzen Sie dazu 'DoOpenPackageWithName'.
Installieren von Packages
Anmerkung: Installieren Sie nur Packages mit IDE-Plugins. Andere Packages zu installieren, kann die IDE instabil machen.
uses PackageIntf, contnrs;
PkgList:=TObjectList.create(true);
try
Pkg:=TLazPackageID.Create;
Pkg.Name:='Cody';
PkgList.Add(Pkg);
// überprüft, ob die IDE die Datei 'cody.lpk' und alle Abhängigkeiten finden kann
// Die IDE gibt einige Warnungen/Bestätigungen aus, falls ihr irgendetwas seltsam vorkommt.
if not PackageEditingInterface.CheckInstallPackageList(PkgList,[]) then
exit;
// in diesem Beispiel haben wir bereits überprüft, deshalb Warnungen überspringen
// und die IDE neu erstellen
if PackageEditingInterface.InstallPackages(PkgList,[piiifSkipChecks,piiifRebuildIDE])<>mrOK then
exit;
finally
PkgList.Free;
end;
Fenster
Grundsätzlich gibt es vier Typen von IDE Fenstern:
- die IDE Hauptleiste ist in Application.MainForm. Sie ist immer präsent.
- schwebende/andockbare Fenster (wie die Quelltext-Editoren, der Objektinspektor und die Meldungen)
- die modalen Formulare, wie der Suchen-Dialog, Einstellungen-Dialog und Rückfragen.
- Hints und Vervollständigungs-Formulare
Hinzufügen eines neuen andockbaren IDE-Fensters
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.
Wie registriert man ein andockbares IDE-Fenster
Vergessen Sie nicht, einen langen, uniquen Namen zu verwenden, der ein gültiger Pascal-Bezeichner ist. Ihr Fenster kann einen beliebigen Titel haben.
uses SysUtils, IDEWindowIntf;
...
var MyIDEWindow: TMyIDEWindow = nil;
procedure CreateMyIDEWindow(Sender: TObject; aFormName: string; var AForm: TCustomForm; DoDisableAutoSizing: boolean);
begin
// check the name
if CompareText(aFormName,MyIDEWindowName)<>0 then exit;
// create the form if not already done and disable autosizing
IDEWindowCreators.CreateForm(MyIDEWindow,TMyIDEWindowm,DoDisableAutosizing,Application);
... init the window ...
AForm:=MyIDEWindow;
end;
procedure Register;
begin
IDEWindowCreators.Add('MyIDEWindow',@CreateMyIDEWindow,nil,'100','50%','+300','+20%');
// the default boundsrect of the form is:
// Left=100, Top=50% of Screen.Height, Width=300, Height=20% of Screen.Height
// when the IDE needs an instance of this window it calls the procedure CreateMyIDEWindow.
end;
Anzeigen eines IDE-Fensters
Benutzen Sie nicht Show. Nehmen Sie stattdessen:
IDEWindowCreators.ShowForm(MyIDEWindow,false);
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.
Anmerkungen über IDEWindowCreators und SimpleLayoutStorage
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.
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.
CodeTools in der IDE
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 (deutsch).
Bevor Sie irgendeine der Codetools-Funktionen in der IDE aufrufen, sollten Sie die letzten Änderungen im Quelltexteditor in den Codetools-Puffern speichern:
uses LazIDEIntf;
...
// save changes in source editor to codetools
LazarusIDE.SaveSourceEditorChangesToCodeCache(-1); // -1: commit all source editors
Hinzufügen einer resource Direktive zu einer Datei
Dies fügt eine {$R example.res} Direktive zu einer Pascal Unit hinzu:
procedure AddResourceDirectiveToPascalSource(const Filename: string);
var
ExpandedFilename: String;
CodeBuf: TCodeBuffer;
begin
// make sure the filename is trimmed and contains a full path
ExpandedFilename:=CleanAndExpandFilename(Filename);
// save changes in source editor to codetools
LazarusIDE.SaveSourceEditorChangesToCodeCache(-1);
// die Datei laden
CodeBuf:=CodeToolBoss.LoadFile(ExpandedFilename,true,false);
// die resource Direktive hinzufügen
if not CodeToolBoss.AddResourceDirective(CodeBuf,'example.res') then
LazarusIDE.DoJumpToCodeToolBossError;
end;
Die Codetools stellen auch Funktionen wie FindResourceDirective und RemoveDirective zur Verfügung.
Die Suchpfade für Units und Include-Dateien ermitteln
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:
uses CodeToolManager;
...
Dir:=''; // das leere Verzeichnis ist für neue Dateien und hat die selben Einstellungen wie das Projektverzeichnis
// ermittelt die Suchpfade für Include-Dateien:
Path:=CodeToolBoss.GetIncludePathForDirectory(Dir);
// ermittelt die Suchpfade für Units:
// Dieser Suchpfad wird an den Compiler übergeben.
// Er enthält die Package-Ausgabe-Verzeichnisse, aber nicht die Package-Quell-Verzeichnisse.
Path:=CodeToolBoss.GetUnitPathForDirectory(Dir);
// zusätzliche Unit-Suchpfade nur für die IDE können auftreten (werden nicht an den Compiler übergeben)
Path:=CodeToolBoss.GetSrcPathForDirectory(Dir);
// der vollständige Suchpfad enthält auch alle Package-Quell-Pfade für Units:
Path:=CodeToolBoss.GetCompleteSrcPathForDirectory(Dir);
Quelltext-Editor
Aktiver Quelltext-Editor
uses SrcEditorIntf;
...
Editor:=SourceEditorManagerIntf.ActiveEditor;
if Editor=nil then exit;
Filename:=Editor.FileName;
ScreenPos:=Editor.CursorScreenXY;
TextPos:=Editor.CursorTextXY;
SynEdit
Die Einstellungen für einen TSynEdit holen
Wenn Sie einen TSynEdit in einem Dialog haben und Sie wollen die selbe Schriftart und die selben Einstellungen wie im Quelltext-Editor verwenden::
uses SrcEditorIntf;
...
SourceEditorManagerIntf.GetEditorControlSettings(ASynEdit);
Die Einstellungen für einen SynEdit-Highlighter holen
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:
uses SrcEditorIntf;
...
SourceEditorManagerIntf.GetHighlighterSettings(ASynHighlighter);
Siehe für ein Beispiel auch: TSQLStringsPropertyEditorDlg.Create in der Unit SQLStringsPropertyEditorDlg.
Hilfe
Hilfe für die Quellen hinzufügen
Erzeugen sie zuerst eine THelpDatabase:
HelpDB := TFPDocHTMLHelpDatabase(
HelpDatabases.CreateHelpDatabase('EinNameIhrerWahlFürDieDatenbank',
TFPDocHTMLHelpDatabase,true));
HelpDB.DefaultBaseURL := 'http://ihre.hilfe.org/';
FPDocNode := THelpNode.CreateURL(HelpDB,
'Package1 - A new package',
'file://index.html');
HelpDB.TOCNode := THelpNode.Create(HelpDB,FPDocNode);// einmal als Inhaltsverzeichnis
DirectoryItem := THelpDBISourceDirectory.Create(FPDocNode,'$(PkgDir)/lcl',
'*.pp;*.pas',false);// und einmal als normale Seite
HelpDB.RegisterItem(DirectoryItem);
Zeilen zum Nachrichtenfenster hinzufügen
unit IDEMsgIntf;
...
var Dir: String;
begin
Dir:=GetCurrentDir;
IDEMessagesWindow.BeginBlock;
IDEMessagesWindow.AddMsg('unit1.pas(30,4) Error: Identifier not found "a"',Dir,0);
IDEMessagesWindow.EndBlock;
end;