![]() |
Komponente mit TStrings Property erstellen
Hallo,
wie der Titel schon aussagt, habe ich ein kleines Problem beim Erstellen einer Komponente, welche ein TStrings Objekt als Property im OI anbieten soll. Ich habe mich beim Erstellen, an diverse Tutorials gehalten (zumindest versucht) aber jedesmal, wenn ich die Komponente dann auf ein Formular ziehe, der Property SQL (das ist die TStrings Property) einen String zuweise und das ganze dann noch ein zweites mal versuche, bekomme ich Zugriffsverletzungen, so, dass nur noch das Beenden von Delphi hilft. Ich verwende Delphi 7 Professional.
Delphi-Quellcode:
Was mache ich da nur falsch?
unit GSQuery;
interface uses SysUtils, Classes; type TGSQuery = class(TComponent) private FSQL: TStringList; procedure setSQL(const Value: TStringList); { Private-Deklarationen } protected { Protected-Deklarationen } public { Public-Deklarationen } constructor Create(aOwner: TComponent); override; destructor Destroy; override; published { Published-Deklarationen } property SQL: TStringList read FSQL write setSQL; end; procedure Register; implementation procedure Register; begin RegisterComponents('GS', [TGSQuery]); end; { TGSQuery } constructor TGSQuery.Create(aOwner: TComponent); begin inherited; FSQL := TStringList.Create; end; destructor TGSQuery.Destroy; begin FSQL.Free; inherited; end; procedure TGSQuery.setSQL(const Value: TStringList); begin FSQL := Value; end; end. |
Re: Komponente mit TStrings Property erstellen
Hallo Günter,
der Fehler steckt in der Setter-Methode. Durch die direkte Zuweisung überschreibst du die im Constructor initialisierte Referenz auf das TStringList-Objekt mit einem neuen Zeiger, was zunächst nur zu einem Speicherleck führt. Gleichzeitig übernimmt aber nun das Query-Objekt die Verantwortung für die übergebene Liste, die du vermutlich nach der Zuweisung zur SQL-Eigenschaft freigibst. Damit ist dann der Zeiger innerhalb des Query-Objekts ungültig! Besser ist es, im Setter den Inhalt der Liste zu kopieren:
Delphi-Quellcode:
Noch ein Vorschlag: ändere den Datentyp von FSQL ab in TStrings. Dadurch kannst du später beliebige TStrings-Nachfolger (z.B. TMemo.Lines) zuweisen. Im Constructor von TGSQuery muß natürlich weiterhin ein TStringList-Objekt instanziiert werden, da TStrings abstrakte Methoden enthält.
FSQL.Assign(Value);
Gruß Hawkeye |
Re: Komponente mit TStrings Property erstellen
Danke :)
Wenn ich Assign verwende klappt es, ein Query Objekt kommt aber nicht wirklich vor, das ist wirklich der komplette Quelltext der Komponente ... die Query kommt erst später dazu :) Das mit TStrings habe ich aber nicht hinbekommen, da meckert der Compiler immer über inkompatible Typen.
Delphi-Quellcode:
unit GSQuery;
interface uses SysUtils, Classes; type TGSQuery = class(TComponent) private FSQL: TStringList; procedure setSQL(const Value: TStrings); { Private-Deklarationen } protected { Protected-Deklarationen } public { Public-Deklarationen } constructor Create(aOwner: TComponent); override; destructor Destroy; override; published { Published-Deklarationen } property SQL: TStrings read FSQL write setSQL; end; procedure Register; implementation procedure Register; begin RegisterComponents('GS', [TGSQuery]); end; { TGSQuery } constructor TGSQuery.Create(aOwner: TComponent); begin inherited; FSQL := TStringList.Create; end; destructor TGSQuery.Destroy; begin FSQL.Free; inherited; end; procedure TGSQuery.setSQL(const Value: TStrings); begin FSQL.Assign(Value); end; end. |
Re: Komponente mit TStrings Property erstellen
Du mußt die Deklaration im private-Abschnitt ebenfalls ändern:
Delphi-Quellcode:
Falls du innerhalb der Komponente einmal auf die TStringList-Eigenschaften zugreifen mußt, benötigst du einen TypeCast:
private
FSQL: TStrings;
Delphi-Quellcode:
Bei der SQL-Eigenschaft sehe ich diese Notwendigkeit aber nicht.
TStringList(FSQL).Sorted := True;
PS: mit "Query-Objekt" meinte ich eine Instanz deiner TGSQuery-Klasse. Gruß Hawkeye |
Re: Komponente mit TStrings Property erstellen
Dankeschön, jetzt funktioniert das mal soweit wie ich es wollte.
|
AW: Komponente mit TStrings Property erstellen
Hallo zusammen,
das Thema ist zwar schon älter - ich habe aber bei gleichem Source-Code folgendes Problem: Im OI kann ich schön Strings in die Stringliste eintragen (mit dem automatisch öffnenden String-Listen-Editor). Soweit so gut. Wenn ich das Programm aber starte, dann sind die eingetragenen Werte nicht mehr vorhanden --> gibt es da einen Trick? Wo sollen die auch her kommen?:shock:
Code:
Im Konstruktor wird FSQL erzeugt --> ist also LEER.:?
constructor TGSQuery.Create(aOwner: TComponent);
begin inherited; FSQL := TStringList.Create; end; WIE komme ich nun an die zur Designzeit eingetragenen Werte?:cyclops: Wäre schön, wenn jemand eine Antwort für mich hätte. Viele Grüße, Poolspieler |
AW: Komponente mit TStrings Property erstellen
Hallo,
ich bin ein bisschen weiter: In FSQL sind die Werte schon vorhanden. Allerdings erst nach einem noch unbekannten Zeitpunkt. Problem ist, dass ich versuche, diese Werte im CONSTRUCTOR einer Combobox zuzuweisen. Und zum Zeitpunkt des Konstruktors ist FSQL tatsächlich noch LEER!
Code:
Frage:
constructor TGSQuery.Create(aOwner: TComponent);
begin inherited; FSQL := TStringList.Create; end; combobox.Items.Assign(FSQL); WANN werden die Werte nach FSQL geladen? Ich habe schon das Ereignis AfterConstruction probiert --> da ist FSQL noch LEER! Mit dem Debugger konnte ich den Zeitpunkt auch noch nicht finden. :( Hat jemand eine Idee? Viele Grüße, Poolspieler |
AW: Komponente mit TStrings Property erstellen
Hallo,
hast Du denn einen Setter für FSQL in Deiner Klasse TGSQuery? Schau Dir mal den Quellcode in ![]() Gruß |
AW: Komponente mit TStrings Property erstellen
Hallo Volker,
danke für Deine Antwort! Ja, habe ich schon. Allerdings stand ich auch gerade ganz schön auf der Leitung: Im Konstruktor muss es natürlich heißen:
Code:
Was will ich denn mit ZWEI Listen???????? :stupid:
constructor TGSQuery.Create(aOwner: TComponent);
begin inherited; ... combobox := TComboBox.Create(Self); ... FSQL := combobox.Items; // und NICHT: //FSQL := TStringList.Create; end; Es ist halt doch schon spät... Viele Grüße, Poolspieler |
AW: Komponente mit TStrings Property erstellen
Noch eine weiterfuehrende Frage,
ich habe auch eine TStrings Liste in den Properties einer eigenen Komponente. Zur Designzeit werden die eingetragenen Werte in der Liste durch eine Setter procedure uebernommen. Nun werden die eigentragenen Werte in der Stringliste dazu verwendet ein Array zu fuellen (wird ebenfalls in der Setter procedure erledigt). Das funktioniert waehrend des Designs prima, allerdings ist das Array zur Laufzeit wieder leer. Die Komponente ist von TPaintBox abegeleitet. Da das Array vom Typ record ist und einige werte zur Laufzeit geaendert werden kann ich das Erstellen des Arrays nicht einfach in die paint procedure packen, da sonst jedesmal standardwerte im Array stehen. Gibt es eine procedure die nur einmal nach dem constructor ausgefuehrt wird? Gutelo Edit: Habs jetzt so geloest in der paint procedure auch wenns nich ganz optimal ist: if Length(Arr) = 0 then FillArr(SList, Arr); Arr ist das Array, SList ist TStrings mit Werten und FillArr eine Prozedur die die Werte aus SList in Arr eintraegt. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:18 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