Hi allseits,
kennt ihr das Gefühl, wenn man als Esel tagelang hinter der Möhre hergewackelt ist, und sie einem im letzen Moment vor der Nase weggezogen wird? So gehts mir im Moment. Wer kann helfen?
Zum Problem: die an sich sehr geniale VirtualTreeView Komponente hat meiner Meinung nach einen grausam schwach integrierten String-Editor. Kein Nutzer ist im Jahr 2015 bereit, zum Editieren eines Knotens die Sequenz "Anpeilen - Anklicken - F2 drücken - Schreiben - F2 drücken" abzuarbeiten.
Erst mal habe ich versucht, mich billig aus der Affäre zu ziehen:
Code:
procedure TClientMainForm.VirtualStringTreeFocusChanged
(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex);
begin
VirtualStringTree.EditNode(Node, Column);
end;
Das öffnet automatisch den Editor, wann immer man sich im Tree auf ein Feld, ich nenne das mal so, bewegt, in dem man zuvor mit dem OnEditing Handler die Editierbarkeit gegeben hat. Prima, das klappt - zur Hälfte. Man kommt nämlich aus dem Feld nicht mehr heraus, außer man hämmert auf Eingabe (unterbricht den Arbeitsfluss), drückt 3 Mal (Tab) oder durch [F2]. Wenn Du das Projekt im Anhang laufen lässt, siehst Du das Problem in Spalte 2, woch den Originaleditor eingehängt habe. Man möchte sich im Jahr 2015 mit den Cursor-Auf und Cursor-Ab Tasten aus dem Feld bewegen können. Leider ist der VirtualTreeView so programmiert dass er Cursor-Auf und Cursor-Ab im eingebauten String Editor behandelt, und deshalb bewegen diese beiden Tasten - was ziemlicher Schmarrn ist - im Eingabefeld den Cursor nach links und rechts, statt das Feld zu verlassen.
Nun kann man ja auch seinen eigenen Editor integrieren. Bei den Lazarus Jungs bin ich fündig geworden:
http://www.lazarusforum.de/viewtopic.php?f=18&t=8317
und ich habe den Code durch einige geringfügige Änderungen auf Delphi (XE7) ans laufen bekommen. Kitzligste Stelle war dabei die Destroy Routine:
Code:
destructor TVTStringEditLink.Destroy;
begin
Application.ReleaseComponent(FEdit);
inherited;
end;
Für Application.ReleaseComponent scheint es in Delphi keine Enstprechung zu geben, ich habe dann - mit ganz schlechtem Gewissen - diesen Code verwendet:
Code:
destructor TVTStringEditor.Destroy;
begin
FEdit.Free;
inherited;
end;
Um den Editor "barrierefrei" einzuhängen habe ich die Möglichkeiten von VirtualTreeView eingesetzt:
Code:
procedure TForm1.VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex);
begin
vst.EditNode(Node,Column); // Editor beim betreten des Feldes sofort aufrufen
end;
procedure TForm1.VSTCreateEditor(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; out EditLink: IVTEditLink);
begin
EditLink := NIL;
case Column of
1: EditLink:=TStringEditLink.Create; // der alte Editor
2: EditLink:=TVTStringEditor.Create; // der neue Editor
end;
end;
Der erste Rundblick war begeisternd: ich kann mich nun in Spalte 2 frei mit den Cursortasten durch den Treeview bewegen und Werte eingeben, Teilziel erreicht. Tage später hat die Kommponente aber leider zurückgeschlagen: wenn ich versuche, den Wert in der untersten Zeile zu ändern, bekomme ich - 1000 Codezeilen weiter in den Eingeweiden der
VCL Library - eine Schutzverletzung. Um das letzte Feld zu verlassen muss man [Enter] nehmen, da es mit Pfeil-Unten richtiger Wese nicht weiter geht. Und dann knallt es (siehe Attachment "crash.jpg").
Code:
procedure TCustomEdit.KeyDown(var Key: Word; Shift: TShiftState);
var
LEditLink: Boolean;
begin
inherited;
LEditLink := Observers.IsObserving(TObserverMapping.EditLinkID); <-- hier kracht es intern, Observers liefert NIL --> kabumm.
Verursacher dürfte der Handler für VK_ENTER sein:
Code:
VK_RETURN:
begin
FTree.EndEditNode;
Key := 0;
if (ssShift in Shift) then
node := FTree.GetPreviousVisible(FNode, True)
else
node := FTree.GetNextVisible(FNode, True);
if node <> nil then
begin
FTree.Selected[node] := true;
FTree.EditNode(node, FTree.FocusedColumn);
end;
end;
Wenns keinen nächsten Node mehr gibt, wird Node zu NIL gesetzt. Gut, das klingt plausibel, aber irgendwo in der Logik ist dennoch ein versteckter Fehler, denn das führt unmittelbar zu abstürzenden Observer. Oder ich belle die ganze Zeit am falschen Baum hoch, weil ich die Logik von VirtualTreeView überhaupt nicht verstanden habe, und die Logik wie man seinen eigenen String Editor einhängt nur ansatzweise.
Wer kann mir helfen, das Projekt wieder in Gang zu bringen? Im Attachment findest Du das komplette Demo-Projekt, es handelt sich um eine aufgebohrte Version eines VirtualTreeView Tutorials, in der ich den verbesserten Editor eingefügt habe, um das Problem zu zeigen, sowie den kompletten Source-Ast des VirtualTreeViews mit dem ich gerade arbeite (es ist eine compilierte, aber im übrigen unveränderte D7 Kopie des aktuellen VirtualTreeView von GitHub).
Herzliche Grüsse, und vielen Dank schon alleine fürs lesen dieses länglichen Postings
Armin.