Ich möchte in einem Programm den TVirtualStringTree verwenden und darin auch einen sog. Inplace Editor.
Wenn man in den Quellcode von Laz.VirtualTrees schaut, stellt man fest, daß diese mit Hilfe von Interfaces (IVTEditLink) implementiert werden können.
Eine spezielle TStringEditLink Implementierung ist dort ebenfalls zu finden und funktioniert auch tadellos.
Nun hatte ich aber den Anspruch, keinen einfachen Stringeditor, sondern eine Combobox "inplace" zu basteln.
Wenn man Tante Google fragt, stößt man u.a. auf dieses Beispiel.
Da werden in der Methode PrepareEdit hart codiert, einige Items hinzugefügt.
Das hat mir nicht gefallen und ich wollte einen Event zur Verfügung stellen, der eine von der Anwendung bereitgestellte Methode zum befüllen der Items verwendet und innerhalb von PrepareEdit aufgerufen wird.
Dabei musste ich feststellen, daß das auch einwandfrei compiliert, aber nicht funktioniert, weil der zuvor zugewiesene Event auf einmal nil ist!
Um das näher zu beleuchten, habe ich eine kleine Testanwendung geschrieben und dabei festgestellt, daß die Ursache der Zugriff auf die Instanz der Editorklasse über die Schnittstellenvariable ist. Das klingt kompliziert, aber wird im anhängenden Beispiel klarer.
Die Klasse TCombobanane ist eine Implementation des Interfaces IBanane und definiert zusätzlich den Event OnFillItems, welcher nach dem erzeugen zugewiesen und in Prepare aufgerufen wird.
Die Anwendung hat zwei Buttons. Bei dem einen wird OnFillItems direkt über die Interfacevariable ifObject aufgerufen (Was schonmal eine Compilerwarnung verursacht (ifomain.pas(88,5) Warning: Class types "IBanane" and "TComboBanane" are not related) - wieso?)
Bei dem zweiten über einen Zwischenschritt, in dem die Instanz über eine Methode GetObj ermittelt wird, die einfach nur self zurückliefert.
Für mein Verständnis sollte das Verhalten in beiden Fällen eigentlich gleich sein.
Code: Alles auswählen
procedure TForm1.btnCreateComboClick(Sender: TObject);
var obj : TObject;
begin
ifObject := TComboBanane.Create;
if (Sender = btnCreateComboIface) then
TComboBanane(ifObject).OnFillItems := @SetItems // <- wird mit Warnung compiliert, funktioniert aber nicht. fOnFillItems bleibt nil
else begin
obj := ifObject.GetObject;
TComboBanane(Obj).OnFillItems := @SetItems; // <- funktioniert
end;
ifObject.PrepareBanane(Sender as TWinControl);
ifObject.UseBanane;
end;