![]() |
VirtualTreeView Editfelder, ComboBox und andere
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 |
AW: VirtualTreeView Editfelder, ComboBox und andere
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
Delphi-Quellcode:
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).
IVTEditLink
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
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;
Delphi-Quellcode:
,
OnEditing
Delphi-Quellcode:
und
OnEdited
Delphi-Quellcode:
. Im
OnEditCancelled
Delphi-Quellcode:
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
OnEditCancelled
Delphi-Quellcode:
Event wird eigentlich nur der Start des Editiervorganges mit Hilfe des
OnEditing
Delphi-Quellcode:
Parameters erlaubt bzw. verweigert (abhängig von Node und Column und evtl. anderen Faktoren). Und schlussendlich im
Allowed
Delphi-Quellcode:
Event kann dann der geänderte Status übernommen und gespeichert/verarbeitet werden.
OnEdited
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. |
AW: VirtualTreeView Editfelder, ComboBox und andere
Liste der Anhänge anzeigen (Anzahl: 1)
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 |
AW: VirtualTreeView Editfelder, ComboBox und andere
Liste der Anhänge anzeigen (Anzahl: 1)
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:
Und das hier muss noch in die PrepareEdit Funktion hinein:
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;
Delphi-Quellcode:
Ansonsten bekommst du beim Ausführen eine AV wegen einer nicht erzeugten Komponente.
Self.FEdit := TEdit.Create(Self.FTree);
Self.FEdit.Visible := False; Self.FEdit.Parent := Self.FTree; |
AW: VirtualTreeView Editfelder, ComboBox und andere
Ein guter Ausgangspunkt sind auch die vorgefertigten Editoren für TEdit, TMemo, TSpinEdit, TDateTimePicker und TCheckBox:
![]() (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. |
AW: VirtualTreeView Editfelder, ComboBox und andere
Zitat:
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. |
AW: VirtualTreeView Editfelder, ComboBox und andere
Es ist ja ein Open Source Projekt. Insofern sollte es ja möglich sein dies zu ergänzen...
Leider werde ich kaum die Zeit finden... Aber mal schauen, vielleicht geht es ja schnell die alten Units anzupassen. Oder hättest du vielleicht Interesse und die Möglichkeit (lizenzrechtlich meine ich, falls du den nicht privat geschrieben hast) den Quelltext dort zur Verfügung zu stellen, vor allem wenn der noch mehr kann als die alte Demo? |
AW: VirtualTreeView Editfelder, ComboBox und andere
Zitat:
|
AW: VirtualTreeView Editfelder, ComboBox und andere
Liste der Anhänge anzeigen (Anzahl: 1)
Einen schönen guten Abend zusammen,
jetzt habe ich das ganze mal an Hand der vorgenannten Unterlagen und der Andvanced Demo (editors.pas und properties Forms) mir selbst zusammen gebastelt. Allerdings klappt dass mit dem Editieren absoulte noch gar nicht. Anbei mal meine aktuell Version. Gruß Jens |
AW: VirtualTreeView Editfelder, ComboBox und andere
Zitat:
Delphi-Quellcode:
arbeiten damit du dich mal mit dem Tree ein bisschen auseinandersetzt. Ich will jetzt nichts falsches sagen, aber es kommt mir so vor als hättest du noch nicht wirklich viel mit dem VirtualTreeView gearbeitet und die Funktionen noch nicht so ganz verstanden. Ich glaube es wäre sinnvoll, wenn du dich erst einmal mit den Grundfunktionen auseinander setzt und dir mal alle Funktionen und Events anschaust die es gibt. So ganz ohne Grundkenntnisse über den Tree kommt man bei dieser Komponente nicht weit.
vst.AddNode(nil)
Aber bitte korrigiere mich wenn ich falsch liege. Ich habe auf jeden Fall kurz in dein Projekt reingeschaut und würde das alles etwas vereinfachen um nicht allzuviel einzuschränken. Lass erst mal alles zu und dann fang an einzuschränken wenn dein Editor funktioniert. Wenn ich die Zeit finde, dann stelle ich dir ein kleines Beispielprojekt zusammen und versuche das relativ einfach zu halten und evtl. auch noch den Code zu erklären. Komme da wohl aber erst am Wochenende dazu. |
AW: VirtualTreeView Editfelder, ComboBox und andere
Hallo Aviator,
Danke erstmal. Mach Dir aktuell mal keine Arbeit. Ich habe es fast gelöst. Stelle kürzlich ein Musterprojekt ein. Eines fehlt mir aktuell noch. Im EditKeyDown, will ich mit der TAB Taste in die nächste Spalte (Column) springen und diese in den Editmode versetzen. Hierzu vermisse ich eine Methode wie NextVisibleColumn. Das selbe soll dann mit den Taste Links/Rechts passieren...
Delphi-Quellcode:
Vielleicht hat hier noch jemand nee Idee...
case Key of
TAB: begin .... end; VK_Right, VK_Left: begin ... end; Gruß Jens |
AW: VirtualTreeView Editfelder, ComboBox und andere
Zitat:
Delphi-Quellcode:
senden und im Formular mit dem VST darauf reagieren. Beim Drücken von Return schmierte das Programm nämlich mit einer AV ab, was auf den Tree zurückzuführen war und nur damit umgangen werden konnte. Wie es bei der ganz neuen Version aussieht weiß ich nicht, da ich aktuell noch die Version 5.5 verwende. Vielleicht wurde der Fehler darin ja behoben. Evtl. könntest du das auch so machen und dann beim PostMessage im Parameter den Key bzw. einen Wert mitgeben an dem du erkennst, dass du in die nächste Spalte springen willst und dort direkt wieder ein
PostMessage()
Delphi-Quellcode:
ausführst. Eine andere evtl. schönere Lösung habe ich jetzt auf Anhieb beim Schreiben nicht parat. Vielleicht würde mir da noch etwas besseres einfallen, nur hatte ich das bisher eigentlich nicht gebraucht.
BeginEdit(Node, Column)
|
AW: VirtualTreeView Editfelder, ComboBox und andere
Also das mit der "Enter" Taste funktioniert schon ganz gut.
Delphi-Quellcode:
procedure TEditEditLink.EditKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState); var ANode : PVirtualNode; begin case Key of VK_ESCAPE: begin Key := 0; end; VK_RETURN: begin FTree.InvalidateNode(FNode); if (ssShift in Shift) then ANode := FTree.GetPreviousVisible(FNode, True) else ANode := FTree.GetNextVisible(FNode, True); FTree.EndEditNode; if ANode <> nil then FTree.FocusedNode := ANode; Key := 0; if FTree.CanEdit(FTree.FocusedNode, FTree.FocusedColumn) then TVirtualStringTreeHack(FTree).DoEdit; end; VK_TAB: begin end; VK_LEFT, VK_RIGHT: begin end; VK_UP, VK_DOWN: begin FTree.InvalidateNode(FNode); if Key = VK_UP then ANode := FTree.GetPreviousVisible(FNode, True) else ANode := FTree.GetNextVisible(FNode, True); FTree.EndEditNode; if ANode <> nil then FTree.FocusedNode := ANode; Key := 0; if FTree.CanEdit(FTree.FocusedNode, FTree.FocusedColumn) then TVirtualStringTreeHack(FTree).DoEdit; end; end; end; |
AW: VirtualTreeView Editfelder, ComboBox und andere
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo zusammen,
im Anhang mal das aktuelle Musterprojekt. Das Steuern mit den Tasten "Enter", "Shift & Enter" und "Auf & Ab" funktioniert schon mal ganz gut. Auch die verschiedenen Editoren (TEdit, TComboBox) gehen. Das mit der "TAB-Taste" und den "Tasten Rechts & Links" bekomme ich allerdings nicht gelöst. Jemand eine Idee. Ansonsten wäre ich über Kommentare zum Musterprojekt dankbar. Danke schon mal, einen schönen Abend und Gruß Jens |
AW: VirtualTreeView Editfelder, ComboBox und andere
Zitat:
Delphi-Quellcode:
auf und gut ist. Sollte genauso funktionieren, nur sauberer. Habe mir das Projekt jetzt nicht runtergeladen und getestet ob es wirklich funktioniert.
FTree.EditNode(Node, Column)
Zu der Sache mit der Tab Taste vermute ich, dass das Drücken von Tab das Control verlässt und du ggf. sogar im EditMode der aktuellen Node bleibst. Hier müsstest du (wahrscheinlich im KeyPress Event) die Tab Taste abfangen, sodass diese nicht vom System weiterverarbeitet wird. |
AW: VirtualTreeView Editfelder, ComboBox und andere
Delphi-Quellcode:
Hab ich angepasst. Das mit dem Hack, habe ich aus einem Lazarus Forum. if FTree.CanEdit(FTree.FocusedNode, FTree.FocusedColumn) then FTree.EditNode(FTree.FocusedNode, FTree.FocusedColumn); Die TAB Taste, bekomme ich aber auch nicht im KeyPress abgefangen. |
AW: VirtualTreeView Editfelder, ComboBox und andere
Also das Ding bringt mich noch zur Verzweiflung. Es muss doch möglich sein, eine Komponente wie das VST mit der Tastatur annähernd wie Excel bedienen zu können.
Das mit dem "Enter" führt übrigens mittlerweile (nach dem Übernehmen der Daten in den Node) auch zu einer Exception. Hier mal der aktuelle Editor...
Delphi-Quellcode:
Ich will ja eigendlich nur folgende Funktionen:
unit TreeEditors;
interface uses VirtualTrees, Vcl.StdCtrls, Winapi.Windows, System.SysUtils, Winapi.Messages, System.Classes, Vcl.Controls, Vcl.Forms, Vcl.Dialogs; //Eigener Type für die verschiedenen Editfelder ( type TEditValueType = (evtNone { Kein Editiern möglich }, evtNumber { Nur Zahlen - Ein TEdit mit "NumbersOnly = true }, evtString { Text - Ein TEdit }, evtPickString { Text mit fester Auswahlmöglichkeit - TComboBox } ); //Eigene Klasse zur Haltung der Daten type TOMyClass = class private FAInt : integer; //Spalte 1 im VST - eine Zahl FAPickString : string; //Spalte 2 im VST - Eine Text mit fester Auswahlmöglichkeit FAString : string; //Spalte 3 im VST - Eine Text FBString : string; //Spalte 4 im VST - Eine Text FBPickString : string; //Spalte 5 im VST - Eine Text mit fester Auswahlmöglichkeit public property AInt: integer read FAInt write FAInt; property APickString : string read FAPickString write FAPickString; property AString : string read FAString write FAString; property BString : string read FBString write FBString; property BPickString : string read FBPickString write FBPickString; end; //Der Datenrecord für das VST type PMyData = ^TMyData; TMyData = record FValueType: array[0..4] of TEditValueType; //Die Var für den Typ des Editierfeld FObject : TObject; //Das Objekt der Daten FChanged : Boolean; end; //Die Interface-Klasse für den Editor type TEditEditLink = class (TInterfacedObject, IVTEditLink) private FEdit: TWinControl; //FEdit als TWinControl für die verschiedenen Editormöglichkeiten (TEdit, TComboBox etc.) FTree : TVirtualStringTree; //Das VST FNode : PVirtualNode; //Das Node FColumn : Integer; //Der Column protected procedure EditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); //Für die Steuerung der Editorfelder über Tastatur procedure EditKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); //Für die Steuerung der Editorfelder über Tastatur public destructor Destroy; override; //Zur Freigabe der Editor-Controls beim beenden function BeginEdit: Boolean; virtual; stdcall; //Start Editorvorgang function CancelEdit: Boolean; virtual; stdcall; //Abbruch Editorvorgang function EndEdit: Boolean; virtual; stdcall; //Ende Editorvorgang function GetBounds: TRect; virtual; stdcall; //Größe ermitteln function PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean; stdcall; //Erstellen der jeweiligen Editor - Controls procedure ProcessMessage(var Message: TMessage); virtual; stdcall; //Für die Übergabe der Nachrichten des VST an den Editor procedure SetBounds(R: TRect); stdcall; //Größe der Editorfelder setzen end; implementation uses fMain; { TEditEditLink } function TEditEditLink.BeginEdit: Boolean; begin //Prüfung um welches Control es sich handelt und entsprechend aktivieren if FEdit is TEdit then begin FEdit.Show; //Anzeigen FEdit.SetFocus; //Focus zuweisen TEdit(FEdit).SelectAll; //Text im TEdit komplett selektieren end else if FEdit is TComboBox then begin FEdit.Show; //Anzeigen FEdit.SetFocus; //Focus zuweisen TComboBox(FEdit).SelectAll; //Text im TEdit komplett selektieren end; end; function TEditEditLink.CancelEdit: Boolean; begin Result := True; //Abbruch erfolgt FEdit.Hide; //Control auf Visible false end; destructor TEditEditLink.Destroy; begin FEdit.Free; //Control nach beenden des Editors wieder freigeben inherited; end; procedure TEditEditLink.EditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); var ANode : PVirtualNode; CanAdvance : Boolean; AColumn : TColumnIndex; begin case Key of VK_ESCAPE: begin Key := 0; end; VK_RETURN: begin if FEdit is TEdit then begin FTree.InvalidateNode(FNode); if (ssShift in Shift) then ANode := FTree.GetPreviousVisible(FNode, True) else ANode := FTree.GetNextVisible(FNode, True); FTree.EndEditNode; if ANode <> nil then FTree.FocusedNode := ANode; Key := 0; if FTree.CanEdit(FTree.FocusedNode, FTree.FocusedColumn) then FTree.EditNode(FTree.FocusedNode, FTree.FocusedColumn); end else if FEdit is TComboBox then begin FTree.InvalidateNode(FNode); if (ssShift in Shift) then ANode := FTree.GetPreviousVisible(FNode, True) else ANode := FTree.GetNextVisible(FNode, True); FTree.EndEditNode; if ANode <> nil then FTree.FocusedNode := ANode; Key := 0; if FTree.CanEdit(FTree.FocusedNode, FTree.FocusedColumn) then FTree.EditNode(FTree.FocusedNode, FTree.FocusedColumn); end; end; VK_TAB: begin end; VK_LEFT, VK_RIGHT: begin end; VK_UP, VK_DOWN: begin if FEdit is TEdit then begin FTree.InvalidateNode(FNode); if Key = VK_UP then ANode := FTree.GetPreviousVisible(FNode, True) else ANode := FTree.GetNextVisible(FNode, True); FTree.EndEditNode; if ANode <> nil then FTree.FocusedNode := ANode; Key := 0; if FTree.CanEdit(FTree.FocusedNode, FTree.FocusedColumn) then FTree.EditNode(FTree.FocusedNode, FTree.FocusedColumn); end else if FEdit is TComboBox then begin TComboBox(FEdit).DroppedDown := True; end; end; end; end; procedure TEditEditLink.EditKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); begin case Key of VK_ESCAPE: begin FTree.CancelEditNode; Key := 0; end; end; end; function TEditEditLink.EndEdit: Boolean; var Data: PMyData; Buffer: array[0..1024] of Char; S: UnicodeString; I: Integer; begin Result := True; Data := FTree.GetNodeData(FNode); case FColumn of 0: begin S := TEdit(FEdit).Text; if S <> IntToStr(TOMyClass(Data.FObject).FAInt) then begin TOMyClass(Data.FObject).FAInt := StrToInt(S); Data.FChanged := True; end; end; 1: begin S := TComboBox(FEdit).Text; if S <> TOMyClass(Data.FObject).FAPickString then begin TOMyClass(Data.FObject).FAPickString := S; Data.FChanged := True; end; end; 2: begin S := TEdit(FEdit).Text; if S <> TOMyClass(Data.FObject).FAString then begin TOMyClass(Data.FObject).FAString := S; Data.FChanged := True; end; end; 3: begin S := TEdit(FEdit).Text; if S <> TOMyClass(Data.FObject).FBString then begin TOMyClass(Data.FObject).FBString := S; Data.FChanged := True; end; end; 4: begin S := TComboBox(FEdit).Text; if S <> TOMyClass(Data.FObject).FBPickString then begin TOMyClass(Data.FObject).FBPickString := S; Data.FChanged := True; end; end; end; if Data.FChanged then begin FTree.InvalidateNode(FNode); { z.B. zusätzlich Update Datenbank } end; FEdit.Hide; end; function TEditEditLink.GetBounds: TRect; begin Result := FEdit.BoundsRect; //Größe ermitteln end; function TEditEditLink.PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean; var Data: PMyData; FValueType : TEditValueType; begin Result := True; FTree := Tree as TVirtualStringTree; FNode := Node; FColumn := Column; FEdit.Free; FEdit := nil; Data := FTree.GetNodeData(FNode); FValueType := Data.FValueType[FColumn]; case FValueType of evtNumber: begin FEdit := TEdit.Create(FTree); TEdit(FEdit).OnKeyDown := EditKeyDown; TEdit(FEdit).OnKeyUp := EditKeyUp; TEdit(FEdit).Text := IntToStr(TOMyClass(Data.FObject).FAInt); FEdit.Visible := False; FEdit.Parent := FTree; end; evtString: begin FEdit := TEdit.Create(FTree); TEdit(FEdit).OnKeyDown := EditKeyDown; TEdit(FEdit).OnKeyUp := EditKeyUp; case FColumn of 2: TEdit(FEdit).Text := TOMyClass(Data.FObject).FAString; 3: TEdit(FEdit).Text := TOMyClass(Data.FObject).FBString; end; FEdit.Visible := False; FEdit.Parent := FTree; end; evtPickString: begin FEdit := TComboBox.Create(FTree); TComboBox(FEdit).OnKeyDown := EditKeyDown; TComboBox(FEdit).OnKeyUp := EditKeyUp; FEdit.Visible := False; FEdit.Parent := FTree; case FColumn of 1: begin TComboBox(FEdit).Text := TOMyClass(Data.FObject).FAPickString; TComboBox(FEdit).Items.Add('Listenauswahl Text 1'); TComboBox(FEdit).Items.Add('Listenauswahl Text 2'); TComboBox(FEdit).Items.Add('Listenauswahl Text 3'); TComboBox(FEdit).Items.Add('Listenauswahl Text 4'); TComboBox(FEdit).Items.Add('Listenauswahl Text 5'); end; 4: begin TComboBox(FEdit).Text := TOMyClass(Data.FObject).FBPickString; TComboBox(FEdit).Items.Add('Zweite Auswahl Text 1'); TComboBox(FEdit).Items.Add('Zweite Auswahl Text 2'); TComboBox(FEdit).Items.Add('Zweite Auswahl Text 3'); end; end; end else begin Result := False; end; end; end; procedure TEditEditLink.ProcessMessage(var Message: TMessage); begin if Assigned(FEdit) then FEdit.WindowProc(Message); end; procedure TEditEditLink.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; end. VK_ENTER - eine Zeile nach unten VK_ENTER/SHIFT - eine Zeile nach oben VK_TAB -eine Spalte nach Links VK_TAB/Shift - eine Spalte nach Rechts VK_UP - eine Zeile nach oben VK_DOWN - eine Zeile nach unten VK_LEFT - eine Spalte nach links VK_RIGHT - eine Spalte nach links |
AW: VirtualTreeView Editfelder, ComboBox und andere
Zitat:
![]() Zitat:
|
AW: VirtualTreeView Editfelder, ComboBox und andere
Zitat:
|
AW: VirtualTreeView Editfelder, ComboBox und andere
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo Jens...:P
Um dir weiteren Frust zu ersparen hätte ich noch einen Alternativvorschlag. Wenn es denn nicht unbedingt die "im Grid editiererei" sein muß kannst du auch folgendes probieren. (Siehe Bild) 1. Die Reihen im Grid (hier Listview) sind quasi immer Readonly. 2. Zum Editieren ein Fenster ohne Rahmen modal auf die Zeile legen. -> Das Editieren kann nur definiert verlassen werden (Save oder Abbruch). 3. Im Design ist man völlig unabhängig von der Grideinteilung obwohl man z.B. die obere Zeile dem Grid nachempfinden kann. 4. So lassen sich auch komplexe Datenobjekte, welche an dem Listeneintrag hängen, bearbeiten ohne massig Spalten zu haben. 5. Man kann auf einer "Kopie" des Datenobjektes arbeiten und nur beim Save die Informationen übertragen. ...was vergessen? :gruebel: Nö. :P doch: 6. Man kann alle Vorzüge eines Formulares nutzen incl. Tab Reihenfolgen, ENTER zum nächsten Control etc. 7. Die Editoren erben alle von einem Basiseditor mit den Basisfunktionalitäten, Events etc. und Buttons. 8. Irgendwann willst du ein anderes Control benutzen...kein Problem. Der Editor bleibt was er ist. :zwinker: |
AW: VirtualTreeView Editfelder, ComboBox und andere
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo haentschman,
Danke für den Tip. Das ist auch meine aktuelle Lösung. Zwar nicht so hübsch wie bei Dir, aber siehe hierzu auch den Screenshot. Ich hätte es halt nur gerne anders gelöst, und dachte, dass das VST das können muss. Trotzdem danke. Ich denke, ich werde mein Formular ein wenig aufhübschen und es dann so realisieren. Gruß Jens |
AW: VirtualTreeView Editfelder, ComboBox und andere
Gern geschehen...8-)
Ich denke, das wichtigste an diesem Konstrukt ist die Unabhängigkeit vom "Parent" darunter. Wie man das dann gestaltet ist die Kür. :P |
AW: VirtualTreeView Editfelder, ComboBox und andere
Hallo haentschman,
wie Positionierst Du die Form auf dem VST. Ich habe das ganze wie folgt versucht, die Position passt aber nicht...
Delphi-Quellcode:
var
CellRect : TRect; Node : PVirtualNode; begin ... CellRect := vst.GetDisplayPosition(Node, Column, false); fForm2.Top := CellRect.Top; fForm2.Left := CellRect.Left; fForm2.ShowModal; end; |
AW: VirtualTreeView Editfelder, ComboBox und andere
Moin...:P
aktuell habe ich noch eine TAdvListview drunter. Die Umstellung auf VT steht auf der TodoListe. :wink: Vieleicht können dir die Brocken ein paar Ansätze liefern. :zwinker: 1. Positionierung Form
Delphi-Quellcode:
2. Im constructor bekommt der Editor(Form) den Parent mit:
class procedure TdTools.SetEditorPositions(ParentListView: TAdvListView; Editor: TForm);
var I: Integer; CurrentPoint: TPoint; CurrentTop: Integer; begin CurrentPoint:= ParentListview.ClientToScreen(Point(30,0)); // 30 = um erste Spalte eingerückt CurrentTop:= CurrentPoint.Y + ParentListview.Selected.Top; // beim Listview hat der selektierte Eintrag Top... VT ? if (CurrentTop + Editor.Height) > Screen.WorkAreaHeight then // klappt den Editor entweder nach unten oder nach oben wenn er nicht mehr auf den Screen paßt begin CurrentTop:= (CurrentTop + ParentListview.ItemHeight) - Editor.Height + 4; end; Editor.Top:= CurrentTop; Editor.Left:= CurrentPoint.X; Editor.Width:= 0; for I := 1 to ParentListView.Columns.Count -1 do begin Editor.Width:= Editor.Width + ParentListView.Column[I].Width; end; Editor.Width:= Editor.Width + conEditorOffsetWidth; // Offset = Feinjustierung für Liniendicke des Grids end;
Delphi-Quellcode:
3. Positionierung auf Spalten
constructor TfoInlineEditorProfiles.Create(Preferences: TdVAPreferences; Database: IdVA_Database; Profile: TProfile; ParentListview: TAdvListView);
begin inherited Create(nil); FLogic:= TInlineEditorProfile.Create(Preferences, Database, Profile); // die BL zum Form FLogic.OnGetProfileGroups:= DoOnGetProfileGroups; FLogic.OnGetParameters:= DoOnGetParameters; FLogic.GetData; pgrProfileProperties.ActivePageIndex:= 0; tvDevices.Width:= FLogic.Preferences.PositionsVA.SplitterEditorProfiles; TdTools.SetControlPosition(ParentListview, 1, True, edtProfileNameLong, daLeft); // Positionierung der 1. Reihe auf die Spalten TdTools.SetControlPosition(ParentListview, 2, True, cbbProfileGroup, daLeft); TdTools.SetControlPosition(ParentListview, 3, True, cbbBatchJob, daLeft); TdTools.SetControlPosition(ParentListview, 4, True, cbbVisualType, daLeft); TdTools.SetControlPosition(ParentListview, 5, True, cbbActive, daLeft); if FLogic.Preferences.PositionsVA.SplitterEditorProfiles > pnlDevices.Width then begin pnlDevices.Width:= FLogic.Preferences.PositionsVA.SplitterEditorProfiles; end else begin FLogic.Preferences.PositionsVA.SplitterEditorProfiles:= pnlDevices.Width; end; end;
Delphi-Quellcode:
class procedure TdTools.SetControlPosition(ParentListView: TAdvListView; ColumnIndex: Integer; SetWidth: Boolean; Control: TControl; Align: TdAlign);
var I: Integer; begin // Todo: Berücksichtigung wenn Control größer als Column Control.Left:= 0; for I := 1 to ColumnIndex do begin if I = 1 then begin Control.Left:= Control.Left; end else begin Control.Left:= Control.Left + ParentListView.Column[I - 1].Width; end; if (I = ColumnIndex) and not (ColumnIndex = 1) then begin Control.Left:= Control.Left - 1; end; end; if SetWidth then begin Control.Width:= ParentListView.Column[ColumnIndex].Width + 1; if Control is TAdvSmoothComboBox then begin TAdvSmoothComboBox(Control).DropDownWidth:= Control.Width; end; end; case Align of daLeft: Control.Left:= Control.Left; daRight: Control.Left:= Control.Left + (ParentListView.Column[ColumnIndex].Width - Control.Width); daCenter: Control.Left:= Control.Left + ((ParentListView.Column[ColumnIndex].Width - Control.Width) div 2); end; end; |
AW: VirtualTreeView Editfelder, ComboBox und andere
Zitat:
|
AW: VirtualTreeView Editfelder, ComboBox und andere
Zitat:
Aber leider bin ich was dass TAB und LEFT/RIGHT Thema angeht noch nicht wirklich weiter. |
AW: VirtualTreeView Editfelder, ComboBox und andere
Also so richtig weiter gekommen bin ich bislang noch. Noch jemand einen Vorschlag?
|
AW: VirtualTreeView Editfelder, ComboBox und andere
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Das hier ist die Methode die bewirkt, dass beim Drücken der Tab-Taste die Komponente nicht verlassen wird. Das kann man dann ja analog dazu in seiner eigenen Editorklasse auch machen und stattdessen in die nächste Column springen.
Delphi-Quellcode:
So, ich hoffe das du damit was anfangen kannst. Solltest du hierzu noch Fragen haben, dann meld dich einfach nochmal.
interface
[...] procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE; [...] implementation [...] procedure TBaseVirtualTree.WMGetDlgCode(var Message: TWMGetDlgCode); begin Message.Result := DLGC_WANTCHARS or DLGC_WANTARROWS; if FWantTabs then Message.Result := Message.Result or DLGC_WANTTAB; end; [...] |
AW: VirtualTreeView Editfelder, ComboBox und andere
Hallo Aviator,
ich spiele gerade ein wenig meiner Deiner Version. Das meiste davon habe ich ja bereits auch schon so gelöst. Allerdings bekomme ich z.B. wenn ich auf
Delphi-Quellcode:
bekomme ich eine Fehlermeldung.
ActiveControl
//z.B. wie bei Dir if (ActiveControl = vstMain) and (Ord(Key) = VK_TAB) then Key := #0; Die
Delphi-Quellcode:
befindet sich ja in der
property ActiveControl;
Delphi-Quellcode:
. Doch auf diese habe ich scheinbar aus meiner eigenen Unit kein Zugriff. Ich habe den Editor in eine eigene Unit gelegt und dort die
vcl.Forms
Delphi-Quellcode:
eingebunden.
vcl.Forms
|
AW: VirtualTreeView Editfelder, ComboBox und andere
ActiveControl ist eine Eigenschaft von TForm und funktioniert deshalb auch nur im Kontext des jeweiligen Formulars.
|
AW: VirtualTreeView Editfelder, ComboBox und andere
Zitat:
|
AW: VirtualTreeView Editfelder, ComboBox und andere
Das habe ich jetzt auch schon so hinbekommen. Ich habe jetzt Deine Editorklasse bei mir integriert und angepasst. Ich kann jetzt komplett navigieren wie gewünscht. Aber das mit dem TAB bekomme ich nicht hin.
Starte ich mein Programm ohne
Delphi-Quellcode:
Dann geht das navigieren auch mit der TAB Taste. Anders nicht. Ich habe jetzt versucht meine Klasse zu erweitern um die TAB Taste abzufangen.
procedure TfKabellisten.vstKabelInEditing(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex; var Allowed: Boolean); begin //Allowed := true; end;
Delphi-Quellcode:
Aber ich bin auch ehrlich, die Funktion verstehe ich absolut nicht. Und im
...
TEditEditLink = class abstract(TBaseDataEditLink) private procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE; ... procedure TEditEditLink.WMGetDlgCode(var Message: TWMGetDlgCode); begin Inherited; Message.Result := Message.Result or DLGC_WANTTAB; end;
Delphi-Quellcode:
Kann man die TAB Taste nicht abfangen. Entnehme ich zumindestens der Delphi Hilfe...
OnKeyDown,
OnKeyUp OnKeyPress
Delphi-Quellcode:
case Key of
VK_TAB: begin //geht so nicht end; |
AW: VirtualTreeView Editfelder, ComboBox und andere
Zitat:
![]() Wenn du die Tab Taste selber behandeln willst, musst du in dem Control, das die entsprechenden Messages bekommt, WM_GETDLGCODE entsprechend des bereits geposteten Codes implementieren. Damit sagst du Windows, dass es die Standardbehandlung für Tab (zum nächsten Steuerelement springen) nicht ausführen und stattdessen die Messages zur Behandlung des Tastendrucks schicken soll. |
AW: VirtualTreeView Editfelder, ComboBox und andere
Zitat:
Schaue ich mir jetzt gleich mal an. Im weiteren habe ich noch ein Problem gefunden. Die Tasten VK_UP, und VK_DOWN gehen. Allerdings, denke ich, das die Funktion ja folgendes machen soll... (siehe Kommentare
Delphi-Quellcode:
Ich hoffe, dass ist so und jemand kann mir mal erklären, woran das Problem liegt und wie ich das abstellen kann.
VK_UP,
VK_DOWN, VK_LEFT, VK_RIGHT: begin CanEndEdit := Shift = []; //CanEndEdit wird gesetzt, wenn keine Shift Taste gedrückt ist if FEdit is TComboBox then //Hier wird geprüft, ob FEdit vom Typ ComboBox ist CanEndEdit := CanEndEdit and not TComboBox(FEdit).DroppedDown; {CanEndEdit wird gesetzt, wenn vorab CanEndEdit gesetzt und TComboBox kein geöffnetes DroppedDown Menü hat. Wäre das DroppedDown Menü geöffnet, soll der nächste Eintrag im Menü gewählt werden. Das funktioniert so nicht. Der nächste Eintrag wird zwar gewählt, aber dann sofort das DroppedDown Menü geschlossen} if CanEndEdit then {Ist kein DroppedDown Menü geöffnet oder kein TComboBox oder kein Shift, müsste dann müsste hier CanEndEdit noch true sein} begin PostMessage(FTree.Handle, WM_KEYDOWN, Key, 0); {Versteh ich wieder nicht so richtig. Ich denke hier wird geprüft, welcher Key und diese Message wird dann verarbeitet. Soll heißen, dass Bewegen mit den Taste Links, Rechts, Auf und Ab. Hier funktioniert die Navigation auch tadellos, allerdings, wird nur beim VK_UP und VK_DOWN die Funktion "SaveChanges" aufgerufen. Dies liegt ja vermutlich daran, das der Node nicht verlassen wird, sondern nur das Column gewechselt. Aber eine Idee zur Lösung fehlt mir trotzdem aktuell} Key := 0; { Abschließen wird der Key auf 0 gesetzt damit keine weitere Bearbeitung entsprechend der normalen Windows Funktionen erfolgt } end; end; Danke nochmal und Gruß Jens |
AW: VirtualTreeView Editfelder, ComboBox und andere
Zitat:
Delphi-Quellcode:
Jetzt gehe ich aktuell davon aus, dass die TAB Taste nicht erkannt wird, weil entweder die Implementation an der falschen Stelle durchgeführt wurde, oder der "Parent" nicht richtig ist...
//es gibt ja den Basis Editor
type TBaseDataEditLink = class(TInterfacedObject, IVTEditLink) protected FEdit : TWinControl; FTree : TVirtualStringTree; FNode : PVirtualNode; FColumn : Integer; IsCanceling: Boolean; // Wird auf True gesetzt, wenn der Bearbeitungsvorgang abgebrochen wird const WM_ENDEDITING = WM_USER + 1311; const FAILURE_CREATECHOICECONTROL = 'Fehler beim Erstellen der Auswahlobjekte!'; protected procedure EditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); virtual; procedure EditKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); virtual; procedure EditKeyPress(Sender: TObject; var Key: Char); virtual; procedure SetBounds(R: TRect); virtual; stdcall; function PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean; virtual; stdcall; procedure GetNodeText; virtual; abstract; procedure SaveChanges; virtual; abstract; public destructor Destroy; override; function BeginEdit: Boolean; virtual; stdcall; function CancelEdit: Boolean; virtual; stdcall; function EndEdit: Boolean; virtual; stdcall; function GetBounds: TRect; virtual; stdcall; procedure ProcessMessage(var Message: TMessage); virtual; stdcall; /// <summary> /// Wird benötigt, damit FEdit von TBaseEditLink nicht auf nil zeigt /// Muss bei jeder Klasse die von TBaseEditLink abgeleitet wird im PrepareEdit ausgeführt werden /// </summary> procedure SetEditComponent(AEditComponent: TWinControl); end; //In diesem Basis Editor habe ich im OnKeyDown die Abfrage der TAB-Taste einbunden procedure TBaseDataEditLink.EditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); var ... begin CanEndEdit := True; ... VK_TAB: begin ShowMessage('tt'); end; ... end; //Dann gibt es ja die abgeleiteten Editoren für TEdit und TComboBox //TComboBox TComboBoxEditLink = class abstract(TBaseDataEditLink) protected FEdit: TComboBox; procedure GetNodeText; override; procedure EditKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); override; function FillOptions(Sender: TComboBox): Boolean; virtual; abstract; function PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean; override; public destructor Destroy; override; function BeginEdit : Boolean; override; end; TEdit TEditEditLink = class abstract(TBaseDataEditLink) protected FEdit: TEdit; procedure GetNodeText; override; abstract; function PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean; override; public destructor Destroy; override; function BeginEdit : Boolean; override; end; { Von diesen Editoren habe ich weitere Editoren abgeleitet, in denen ich dann noch ein paar Details eingebunden habe. z.B. verschiedene Properties etc. } { Hier nehme ich mal als Beispiel eine von } type TKabelbezeichnungEditLink = class(TEditEditLink) private //Hier die implementation der message WM_GETDLGCODE procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE; protected procedure GetNodeText; override; procedure SaveChanges; override; end; { und } procedure TKabelbezeichnungEditLink.WMGetDlgCode(var Message: TWMGetDlgCode); begin Inherited; Message.Result := Message.Result or DLGC_WANTTAB; end; Ich habe hierzu dieses gefunden... ![]() |
AW: VirtualTreeView Editfelder, ComboBox und andere
Zitat:
Delphi-Quellcode:
Funktion den Parent des FEdit mal auf den Tree setzen. Dann nochmal probieren. Wenn es dann nicht funktioniert, dann müsstest du mal schauen, ob die Message evtl. im Tree schon abgefangen und eliminiert wird, sobald sich der Tree im Editmodus befindet. Kann jetzt leider gerade nicht nachschauen bzw. nachprüfen. Aber das wäre jetzt mal ein Ansatz den du austesten könntest.
TBaseDataEditLink.PrepareEdit()
[EDIT]Sorry nicht in der
Delphi-Quellcode:
sondern in einer der nachfolgenden Klassen, in der die Instanz der Komponente erzeugt wird.[/EDIT]
TBaseDataEditLink.PrepareEdit()
|
AW: VirtualTreeView Editfelder, ComboBox und andere
Also ich mache das eigendlich in der Instanz in der ich die Komponente erzeuge...
Delphi-Quellcode:
function TKabelNrEditLink.PrepareEdit(Tree: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex): Boolean; begin inherited; Self.FEdit.Style := csDropDownList; Self.FEdit.OnChange := Change; Self.FEdit.Parent := Self.FTree; end; |
AW: VirtualTreeView Editfelder, ComboBox und andere
Liste der Anhänge anzeigen (Anzahl: 1)
Ergänzend muss ich vieleicht mal noch erklären, dass meine Form mit dem integrierten VST als Form auf einem Panel auf meiner MainForm liegt.
Ich habe meine Programmoberfläche wie folgt gestaltet: 1. MainForm 2. Linkes Seite MainForm ein VST als eine Art Datenexplorer 3. Rechte Seite MainForm ein Panel als Datenpanel auf dem ich je nach Auswahl im vst entsprechende Daten anzeige. Auf dieses Panel werden dann entweder Frames oder in diesem Fall eine Form gelegt und dieser Form ist dann das Panel als Parent zugewiesen. siehe Bild im Anhang.. |
AW: VirtualTreeView Editfelder, ComboBox und andere
Es ist dann vielleicht einfacher, wenn du mit dem Window Detective anschaust welche Messages eigentlich wo landen...
Vielleicht muss WM_GETDLGCODE auch in deinem obersten Formular beantwortet werden. Kann ich das aktuelle Problem in dem Beispiel aus #14 nachvollziehen? Dann schaue ich mit das einmal heute Abend an. |
AW: VirtualTreeView Editfelder, ComboBox und andere
Ich denke schon, aber Du meinst glaube ich #34
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:57 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz