Lagra en sträng (eller ett objekt) med en sträng i en ListBox eller ComboBox

Delphis TListBox och TComboBox visar en lista med objekt - strängar i en "valbar" lista. TListBox visar en rullbar lista, TComboBox visar en listruta.

En gemensam egenskap för alla ovanstående kontroller är artiklar fast egendom. Objekt definierar en lista med strängar som kommer att visas i kontrollen för användaren. När du dubbelklickar på egenskapen Objekt vid designtid kan du "String List Editor" ange strängobjekt. Egenskapen Objekt är faktiskt en ättling av typen TStrings.

Två strängar per artikel i en ListBox?

Det finns situationer när du vill visa en lista med strängar till användaren, till exempel i listboxens kontroll, men också har ett sätt att lagra ytterligare en sträng längs den som visas för användaren.

Dessutom kanske du vill lagra / bifoga mer än bara en "vanlig" sträng till strängen, kanske du vill bifoga ett objekt till objektet (sträng).

ListBox.Items - TStrings "Knows" Objects!

Ge TStrings-objektet ytterligare en titt i hjälpsystemet. Det är Objekt egenskap som representerar en uppsättning objekt som är associerade med var och en av strängarna i egenskapen Strängar - där egenskapen Strängar refererar till de verkliga strängarna i listan.

Om du vill tilldela en andra sträng (eller ett objekt) till varje sträng i listrutan måste du fylla i objektegenskapen vid körning.

Medan du kan använda ListBox.Items.Add metod för att lägga till strängar i listan, för att koppla ett objekt till varje sträng måste du använda ett annat tillvägagångssätt.

De ListBox.Items.AddObject metoden accepterar två parametrar. Den första parametern "Objekt" är artikelns text. Den andra parametern, "AObject" är objektet som är associerat med objektet.

Observera att listrutan exponerar Lägg till vara metod som gör samma sak som Items.AddObject.

Två strängar för en sträng

Eftersom båda artiklarna.AddObject och AddItem accepterar en variabel av typen TObject för deras andra parameter, en rad som:

 // kompilera fel! ListBox1.Items.AddObject ('zarko', 'gajic'); 

kommer att resultera i ett kompileringsfel: E2010 Oförenliga typer: 'TObject' och 'string'.

Du kan inte helt enkelt ange en sträng för objektet eftersom strängvärden i Delphi för Win32 inte är objekt.

För att tilldela en andra sträng till listboxen måste du "omvandla" en strängvariabel till ett objekt - du behöver ett anpassat TString-objekt.

Ett heltal för en sträng

Om det andra värdet du behöver lagra tillsammans med strängobjektet är ett heltal, behöver du faktiskt inte en anpassad TInteger-klass.

 ListBox1.AddItem ('Zarko Gajic', TObject (1973)); 

Linjen ovan lagrar heltalet "1973" tillsammans med den tillagda strängen "Zarko Gajic".

En direkt typecast från ett heltal till ett objekt görs ovan. Parametern "AObject" är faktiskt 4-byte-pekaren (adress) för det tillagda objektet. Sedan i Win32 upptar ett heltal fyra byte - en sådan hård roll är möjlig.

För att få tillbaka heltalet som är associerat med strängen måste du kasta tillbaka "objektet" till heltalvärdet:

 // år == 1973 år: = heltal (ListBox1.Items.Objects [ListBox1.Items.IndexOf ('Zarko Gajic')]); 

En Delphi-kontroll för en sträng

Varför stanna här? Att tilldela strängar och heltal till en sträng i en listruta är, som du just upplevt, en bit kaka.

Eftersom Delphi-kontroller faktiskt är objekt kan du koppla en kontroll till varje sträng som visas i listrutan.

Följande kod läggs till i rubriken ListBox1 (listbox) för alla TButton-kontroller på ett formulär (placera detta i formulärets OnCreate-händelseshanterare) tillsammans med referensen till varje knapp.

 var   idx: heltal; Börja   för idx: = 0 till -1 + ComponentCount do   Börja     om Komponenter [idx] är TButton sedan ListBox1.AddObject (TButton (Components [idx]). Bildtext, Components [idx]);   slutet; slutet; 

För att programmera "klicka" på "andra" -knappen kan du använda nästa uttalande:

 TButton (ListBox1.Items.Objects [1]) klick.; 

Jag vill tilldela mina anpassade objekt till strängobjektet

I en mer generisk situation skulle du lägga till instanser (objekt) av dina egna klasser:

 typ   TStudent = klass   privat     fName: string; fYear: heltal;   offentlig     fast egendom Namn : sträng läst fname;     fast egendom År: heltal läsa fYear;     konstruktör Skapa(const namn : sträng; const år: heltal);   slutet; ... konstruktör TStudent.Create (const namn : sträng; const år: heltal); Börja   fName: = namn; år: = år; slutet; -------- Börja   // lägg till två strängar / objekt -> elever i listan   ListBox1.AddItem ('John', TStudent.Create ('John', 1970)); ListBox1.AddItem ('Jack', TStudent.Create ('Jack', 1982));   // ta den första studenten - John   student: = ListBox1.Items.Objects [0] som TStudent;   // visa Johns år   ShowMessage (IntToStr (student.år)); slutet; 

Vad du skapar måste du gratis

Här är vad Hjälpen har att säga om objekt i TStrings ättlingar: TStrings-objektet äger inte de objekt du lägger till på detta sätt. Objekt som läggs till TStrings-objektet finns fortfarande även om TStrings-instansen förstörs. De måste vara uttryckligen förstörda av ansökan.

När du lägger till objekt i strängar - objekt som du skapar - måste du se till att du frigör det ockuperade minnet, eller så har du ett minnesläckage

En generisk anpassad procedur FreeObjects accepterar en variabel av typen TStrings som dess enda parameter. FreeObjects kommer att frigöra alla objekt som är associerade med ett objekt i stränglistan I exemplet ovan är "studenter" (TStudent-klass) kopplade till en sträng i en listruta, när applikationen är på väg att stängas (huvudformulär OnDestroy-händelse, för exempel), måste du frigöra upptaget minne:

 FreeObjects (ListBox1.Items); 

Obs: Du kallar bara den här proceduren när objekt som tilldelats strängobjekt skapades av dig.