AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi VirtualTreeView Editfelder, ComboBox und andere
Thema durchsuchen
Ansicht
Themen-Optionen

VirtualTreeView Editfelder, ComboBox und andere

Ein Thema von Jens Hartmann · begonnen am 28. Mär 2016 · letzter Beitrag vom 1. Nov 2016
Antwort Antwort
Benutzerbild von Jens Hartmann
Jens Hartmann

Registriert seit: 11. Jan 2009
Ort: Wilnsdorf
1.439 Beiträge
 
Delphi XE2 Professional
 
#1

VirtualTreeView Editfelder, ComboBox und andere

  Alt 28. Mär 2016, 10:03
Hallo zusammen,

ich versuche jetzt schon den ganzen Vormittag eine vernünftige Beschreibung zu den Möglichkeiten der Einbindung von Edits etc. in ein VirtualStringTree zu finden.

Es wird häufig auf die Advanced Demo des VST und auf die Editors.pas verwiesen. Ich bin allerdings ehrlich, verstehen tue ich das ganze aktuell noch nicht. Es stehen scheinbat auch verschiedene Demos zur Verfügung, die aber nicht mehr mit XE2 laufen.

Kann mir eventuell mal jemand einfach eräutern, wie das funktioniert.

Danke und Gruß Jens
Jens Hartmann
Das Leben selber ist zu kurz, also nutze jeden Tag wie er kommt.
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.611 Beiträge
 
Delphi 10.3 Rio
 
#2

AW: VirtualTreeView Editfelder, ComboBox und andere

  Alt 28. Mär 2016, 10:56
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:
  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;
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.

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:
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;
Die Funktion GetNodeText kommt von mir und soll den Text der in der Node steht einfach mal in das neu erstellte Editfeld "kopieren".
Delphi-Quellcode:
procedure TEditEditLink.GetNodeText;
begin
  Self.FEdit.Text := FTree.Text[FNode, FColumn];
end;
Im EndEdit sollten die Änderungen dann gespeichert werden. Ich habe mir jetzt einfach mal einen kleinen Codeausschnitt aus meinen Editorklassen kopiert.
Delphi-Quellcode:
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;
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.
Delphi-Quellcode:
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;
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.
Delphi-Quellcode:
function TBaseDataEditLink.GetBounds: TRect;
begin
  Result := FEdit.BoundsRect;
end;
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.
Delphi-Quellcode:
procedure TBaseDataEditLink.ProcessMessage(var Message: TMessage);
begin
  if Assigned(FEdit) then
    FEdit.WindowProc(Message);
end;
Die CancelEdit Funktion macht eigentlich das was der Name sagt bzw. wird bei Abbrechen des Editiervorganges ausgeführt.
Delphi-Quellcode:
function TBaseDataEditLink.CancelEdit: Boolean;
begin
  Result := True;
  FEdit.Hide;
end;
Im Destructor noch das Editfeld aufräumen damit nichts mehr im Speicher zurückbleibt.
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:
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;
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.


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
  Mit Zitat antworten Zitat
Benutzerbild von Jens Hartmann
Jens Hartmann

Registriert seit: 11. Jan 2009
Ort: Wilnsdorf
1.439 Beiträge
 
Delphi XE2 Professional
 
#3

AW: VirtualTreeView Editfelder, ComboBox und andere

  Alt 28. Mär 2016, 20:07
Hallo Aviator,

leider kann ich das noch nicht so ganz nachvollziehen. Ich habe daher im Anhang mal mein eigenes Demo-Projekt angefügt.

Leider bekomme ich die Klasse schon nicht ans laufen und das Editieren ist auch nicht möglich. Beim Compilieren bringt der Compiler mir schon folgende Fehler:

[DCC Fehler] TreeEditors.pas(17): E2137 Methode 'GetNodeText' nicht in Basisklasse gefunden
[DCC Fehler] TreeEditors.pas(17): E2252 Es gibt bereits eine Methode 'GetNodeText' mit identischen Parametern
[DCC Fehler] TreeEditors.pas(18): E2137 Methode 'PrepareEdit' nicht in Basisklasse gefunden
[DCC Fehler] TreeEditors.pas(25): E2137 Methode 'PrepareEdit' nicht in Basisklasse gefunden
[DCC Fehler] TreeEditors.pas(26): E2252 Es gibt bereits eine Methode 'PrepareEdit' mit identischen Parametern
[DCC Fehler] TreeEditors.pas(9): E2291 Implementierung der Interface-Methode IVTEditLink.PrepareEdit fehlt
[DCC Fehler] TreeEditors.pas(9): E2291 Implementierung der Interface-Methode IVTEditLink.SetBounds fehlt
[DCC Fehler] TreeEditors.pas(71): E2136 Definition für abstrakte Methode 'GetNodeText' nicht erlaubt
[DCC Fehler] TreeEditors.pas(73): E2003 Undeklarierter Bezeichner: 'FTree'
[DCC Fehler] TreeEditors.pas(73): E2003 Undeklarierter Bezeichner: 'FNode'
[DCC Fehler] TreeEditors.pas(91): E2003 Undeklarierter Bezeichner: 'SetBounds'
[DCC Fehler] TreeEditors.pas(95): E2003 Undeklarierter Bezeichner: 'FTree'
[DCC Fehler] TreeEditors.pas(95): E2066 Operator oder Semikolon fehlt
[DCC Fehler] TreeEditors.pas(95): E2003 Undeklarierter Bezeichner: 'FColumn'
[DCC Fehler] TreeEditors.pas(95): E2003 Undeklarierter Bezeichner: 'R'
[DCC Fehler] TreeEditors.pas(15): E2065 Ungenügende Forward- oder External-Deklaration: 'TEditEditLink.GetNodeText'
[DCC Fehler] TreeEditors.pas(18): E2065 Ungenügende Forward- oder External-Deklaration: 'TEditEditLink.PrepareEdit'
[DCC Hinweis] TreeEditors.pas(15): H2219 Das private-Symbol 'GetNodeText' wurde deklariert, aber nie verwendet
[DCC Fataler Fehler] fMain.pas(7): F2063 Verwendete Unit 'TreeEditors.pas' kann nicht compiliert werden
Angehängte Dateien
Dateityp: 7z vstEditorDemo.7z (62,7 KB, 13x aufgerufen)
Jens Hartmann
Das Leben selber ist zu kurz, also nutze jeden Tag wie er kommt.
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.611 Beiträge
 
Delphi 10.3 Rio
 
#4

AW: VirtualTreeView Editfelder, ComboBox und andere

  Alt 28. Mär 2016, 21:21
Also im Prinzip hast du es schon richtig aufgebaut. Aber oben in deinen Methodendeklarationen hast du einige Fehler eingebaut die ich dir dooferweise in meinen Beitrag hineingeschrieben habe. Ich hatte mir das wie gesagt aus mehreren Klassen wieder zu einer zusammengeklickt und dadurch nicht gemerkt, dass die Methoden schon deklariert waren. Habe auch kein Testprogramm geschrieben um die von mir gepostete Klasse noch einmal zu testen.

Hier mal der Klassenheader mit den Methodendeklarationen (ich werde den in meinem Beitrag auch ersetzen):

Delphi-Quellcode:
  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;
Und das hier muss noch in die PrepareEdit Funktion hinein:

Delphi-Quellcode:
  Self.FEdit := TEdit.Create(Self.FTree);
  Self.FEdit.Visible := False;
  Self.FEdit.Parent := Self.FTree;
Ansonsten bekommst du beim Ausführen eine AV wegen einer nicht erzeugten Komponente.
Angehängte Dateien
Dateityp: 7z vstEditorDemo.7z (368,2 KB, 46x aufgerufen)

Geändert von Aviator (28. Mär 2016 um 21:23 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.360 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: VirtualTreeView Editfelder, ComboBox und andere

  Alt 29. Mär 2016, 05:46
Ein guter Ausgangspunkt sind auch die vorgefertigten Editoren für TEdit, TMemo, TSpinEdit, TDateTimePicker und TCheckBox:
http://www.soft-gems.net/index.php/c...rtual-treeview
(ganz unten "Virtual Treeview (editors)")

Die sind zwar schon länger nicht mehr aktualisiert, aber bis vor dem Split der VirtualTrees in mehrere Units funktionierte es damit noch problemlos, jetzt muss vermutlich auch kaum mehr als die uses angepasst werden.

Warum das nicht offiziell mitgepflegt wird, weiß ich nicht. Sinnvoll wäre es.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.611 Beiträge
 
Delphi 10.3 Rio
 
#6

AW: VirtualTreeView Editfelder, ComboBox und andere

  Alt 29. Mär 2016, 12:43
Ein guter Ausgangspunkt sind auch die vorgefertigten Editoren für TEdit, TMemo, TSpinEdit, TDateTimePicker und TCheckBox:
http://www.soft-gems.net/index.php/c...rtual-treeview
(ganz unten "Virtual Treeview (editors)")

[...]

Warum das nicht offiziell mitgepflegt wird, weiß ich nicht. Sinnvoll wäre es.
Da gebe ich dir recht. Wäre wirklich sinnvoll die dann immer anzupassen und auch auf der neuen HomePage als Download zur Verfügung zu stellen. Ich habe mir mittlerweile allerdings meine eigenen Basisklassen erstellt und die auch zum VST gepackt als VirtualTrees.BaseEditors Unit.

Deshalb hatte ich auch im ersten Beitrag ein paar "Schwierigkeiten" da wieder eine funktionierende Klasse zusammenzubasteln. Hatte die wie gesagt nicht getestet und alles nur hier im Editor zusammengebaut. Aber die Demo die ich angehängt hatte sollte jetzt zumindest mal funktionieren.
  Mit Zitat antworten Zitat
Benutzerbild von blawen
blawen

Registriert seit: 30. Nov 2003
Ort: Luterbach (CH)
654 Beiträge
 
Delphi 12 Athens
 
#7

AW: VirtualTreeView Editfelder, ComboBox und andere

  Alt 2. Apr 2016, 10:50
Warum das nicht offiziell mitgepflegt wird, weiß ich nicht. Sinnvoll wäre es.
Zitat vom 13. Juni 2015
Zitat:
With the release 5.4.0 my part on Virtual Treeview's development is over.
It's now maintained by JAM-Software
Roland
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es 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

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:23 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz