|
Registriert seit: 3. Jun 2010 1.611 Beiträge Delphi 10.3 Rio |
#2
Hallo Jens,
also im Grunde ist der Verweis auf die Advanced Demo nicht falsch. Dort wird eigentlich alles gezeigt was man wissen muss. Problem hierbei ist allerdings, dass alles sehr stark zerpflückt wurde um die verwendeten Klassen bei mehreren Demos verwenden zu können. Ich hatte damals das gleiche Problem und musste mich da durch kämpfen. Aber kommen wir mal zum eigentlich wichtigen Teil des Beitrages. Als allererstes solltest du dir eine neue Klasse erstellen die das Interface IVTEditLink implementiert. Das Interface ist die Grundlage dafür, dass der Editor überhaupt funktionieren kann. Es sei denn du machst wirklich alles von Hand. Und das willst du ja nicht (wäre aus schwachsinnig). Die Definition des Interfaces von IVTEditLink steht in der VirtualTrees.pas, trotzdem poste ich diese hier, damit das alles etwas zusammenhängt.
Delphi-Quellcode:
IVTEditLink = interface
['{2BE3EAFA-5ACB-45B4-9D9A-B58BCC496E17}'] function BeginEdit: Boolean; stdcall; // Called when editing actually starts. function CancelEdit: Boolean; stdcall; // Called when editing has been cancelled by the tree. function EndEdit: Boolean; stdcall; // Called when editing has been finished by the tree. Returns True if successful, False if edit mode is still active. function PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean; stdcall; // Called after creation to allow a setup. function GetBounds: TRect; stdcall; // Called to get the current size of the edit window // (only important if the edit resizes itself). procedure ProcessMessage(var Message: TMessage); stdcall; // Used to forward messages to the edit window(s)- procedure SetBounds(R: TRect); stdcall; // Called to place the editor. end;
Delphi-Quellcode:
Ich hoffe ich habe jetzt an dieser Stelle nichts vergessen da ich alles bei mir mit abgeleiteten Klassen gebaut habe. Ich habe mir eine BaseEditor Klasse gebaut wie man sie in der AdvancedDemo auch findet. Diese macht diverse grundlegene Dinge die man sonst bei jeder Art von Komponente noch einmal machen müsste. Kommen wir jetzt zur implementierung der einzelnen Methoden.
TEditEditLink = class (TInterfacedObject, IVTEditLink)
private FEdit: TEdit; FTree : TVirtualStringTree; FNode : PVirtualNode; FColumn : Integer; procedure GetNodeText; public destructor Destroy; override; function BeginEdit: Boolean; virtual; stdcall; function CancelEdit: Boolean; virtual; stdcall; function EndEdit: Boolean; virtual; stdcall; function GetBounds: TRect; virtual; stdcall; function PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean; stdcall; procedure ProcessMessage(var Message: TMessage); virtual; stdcall; procedure SetBounds(R: TRect); stdcall; end; In der PrepareEdit Funktion werden zuerst einmal alle wichtigen Komponenten zwischengespeichert mit denen man arbeiten muss. Also der eigentliche Tree von dem der Editvorgang gestartet wurde, die Node die editiert werden soll und abschließen noch die Column in der editiert werden soll.
Delphi-Quellcode:
function TEditEditLink.PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean;
begin Result := True; FTree := Tree as TVirtualStringTree; FNode := Node; FColumn := Column; end;
Delphi-Quellcode:
Die Funktion GetNodeText kommt von mir und soll den Text der in der Node steht einfach mal in das neu erstellte Editfeld "kopieren".
function TEditEditLink.BeginEdit: Boolean;
begin // Hier kann man diverse Dinge tun, die direkt zu Beginn des Editvorganges gemacht werden sollen // Als Beispiel bei einem Editfeld könnte alles selektiert werden Self.FEdit.Show; Self.FEdit.SetFocus; Self.GetNodeText; Self.FEdit.SelectAll; end;
Delphi-Quellcode:
Im EndEdit sollten die Änderungen dann gespeichert werden. Ich habe mir jetzt einfach mal einen kleinen Codeausschnitt aus meinen Editorklassen kopiert.
procedure TEditEditLink.GetNodeText;
begin Self.FEdit.Text := FTree.Text[FNode, FColumn]; end;
Delphi-Quellcode:
In der SetBounds Procedure wird der erstellten Komponente die Größe zugeteilt die diese haben soll. Die GetColumnBounds Procedure verlangt als zweiten Parameter einen Var-Parameter der die linke Position der Column zurückgibt. Ich weiß nicht mehr wieso ich hier eine Dummy Variable benutzt habe, kann sein, dass hier irgendwo sonst was überschrieben wurde. Kannst du aber gerne ändern bzw. ausprobieren.
function TBaseDataEditLink.EndEdit: Boolean;
begin try SaveChanges; except on e: Exception do MessageBox(FTree.Parent.Handle, PChar(e.Message), 'Fehler', MB_OK or MB_ICONERROR or MB_TASKMODAL); end; Result := True; end;
Delphi-Quellcode:
GetBounds wird von der Treeklasse benötigt, um die "Ränder" der erstellten Komponente zu ermitteln um diese später im Tree richtig zu zeichnen.
procedure TBaseDataEditLink.SetBounds(R: TRect);
var Dummy : Integer; begin FTree.Header.Columns.GetColumnBounds(FColumn, Dummy, R.Right); R.Left := Dummy;// + FTree.Margin * 2; FEdit.Width := R.Width; R.Bottom := Abs(R.Top) + Abs(FTree.NodeHeight[FTree.FocusedNode]); InflateRect(R, 0, 1); FEdit.BoundsRect := R; end;
Delphi-Quellcode:
Die ProcessMessages Procedure hatte ich mir auch nur aus der AdvancedDemo herauskopiert. Die soll wohl nur bewirken, dass alle Nachrichten des Trees an den Editor weitergeleitet werden.
function TBaseDataEditLink.GetBounds: TRect;
begin Result := FEdit.BoundsRect; end;
Delphi-Quellcode:
Die CancelEdit Funktion macht eigentlich das was der Name sagt bzw. wird bei Abbrechen des Editiervorganges ausgeführt.
procedure TBaseDataEditLink.ProcessMessage(var Message: TMessage);
begin if Assigned(FEdit) then FEdit.WindowProc(Message); end;
Delphi-Quellcode:
Im Destructor noch das Editfeld aufräumen damit nichts mehr im Speicher zurückbleibt.
function TBaseDataEditLink.CancelEdit: Boolean;
begin Result := True; FEdit.Hide; end;
Delphi-Quellcode:
destructor TBaseDataEditLink.Destroy;
begin FEdit.Free; inherited Destroy; end; So! An dieser Stelle hätten wir unsere Klasse nun fertig sofern ich nichts vergessen habe. Falls doch, einfach darauf hinweisen. Jetzt müssen wir den Editor nur noch in unserem eigentlichen Programm verwenden. Hierzu müssen wir das OnCreateEditor Event des Trees einbinden. Hier kann noch der Sender, die Column und die Node abgefragt werden um abhängig davon einen entsprechenden Editor zu erzeugen. Der EditLink Parameter ist ein out Parameter und verlangt jetzt eine Instanz eines Interfaces. Hier einfach eine Instanz der vorhin erstellten Klasser erzeugen.
Delphi-Quellcode:
Zusätzlich zum OnCreateEditor Event gibt es noch die beiden Events OnEditing
, OnEdited
und OnEditCancelled
. Im OnEditCancelled
Event kann darauf reagiert werden, was bei Abbruch des Editiervorganges passieren soll. Bspw. kann hier alles wieder auf einen bestimmten Status zurückgesetzt werden oder was auch immer. Im OnEditing
Event wird eigentlich nur der Start des Editiervorganges mit Hilfe des Allowed
Parameters erlaubt bzw. verweigert (abhängig von Node und Column und evtl. anderen Faktoren). Und schlussendlich im OnEdited
Event kann dann der geänderte Status übernommen und gespeichert/verarbeitet werden.
procedure TfrmMain.vstCreateEditor(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex;
out EditLink: IVTEditLink); begin EditLink := TEditEditLink.Create; // Hier sollte eigentlich ein Kommentar stehen den ich jetzt über die Methode gesetzt habe. end; Hoffentlich hat dir diese kleine Einführung geholfen das Thema besser zu verstehen. Ansonsten einfach hier nochmal nachhaken. Ich hatte mich damals auch ewig lange mit diese Thema auseinander gesetzt bis ich es endlich mal verstanden hatte. Geändert von Aviator (28. Mär 2016 um 21:22 Uhr) Grund: Kommentar in Methode wurde abgeschnitten. Klassendeklaration überarbeitet |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |