• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1627
  • Last Modified:

Delphi how to create a new Instance of a Component at runtime. (TStringList)

It's like this
 
Click button 1
Button one will create a new Instance of TStringList with Edit1.Text for the Name
It will then take The Items in the ListBox and Add them to the new instance.

Click Button 2

Go through all instances ot TStringList created on Button1 Click and process them to a Textbox for viewing.

if you needf clarification just ask
0
jamerslong
Asked:
jamerslong
  • 5
  • 4
1 Solution
 
Geert GruwezOracle dbaCommented:
a TStringList doesn't have a property name.
so you need to create a descendant which does have a property Name

this should work ...
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ContNrs;
 
type
  TNamedStringList = class(TStringList)
  private
    fName: string;
  published
  public
    constructor Create(aName: string); reintroduce;
    property Name: string read fName;
  end;
 
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    fSList: TObjectList;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
{ TNamedStringList }
 
constructor TNamedStringList.Create(aName: string);
begin
  inherited Create;
  fName := aName;
end;
 
{ TForm1 }
 
constructor TForm1.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  fSList := TObjectList.Create(True);
end;
 
destructor TForm1.Destroy;
begin
  FreeAndNil(fSList);
  inherited Destroy;
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var item: TStringList;
  I: Integer;
begin
  for I := 0 to fSList.Count - 1 do
    if SameText(TNamedStringList(fSList.Items[I]).Name, Edit1.Text) then
    begin
      ShowMessage('This name allready exists in the list');
      Exit;
    end;
  item := TNamedStringList.Create(Edit1.Text);
  item.AddStrings(ListBox1.Items);
  fSList.Add(item);
end;
 
procedure TForm1.Button2Click(Sender: TObject);
var I: Integer;
  item: TNamedStringList;
begin
  Memo1.Lines.BeginUpdate;
  try
    Memo1.Lines.Clear;
    for I := 0 to fSList.Count - 1 do
    begin
      item := TNamedStringList(fSList.Items[I]);
      Memo1.Lines.Add(item.Name);
      Memo1.Lines.AddStrings(item);
      Memo1.Lines.Add('');
    end;
  finally
    Memo1.Lines.EndUpdate;
  end;
end;
 
end.

Open in new window

0
 
jamerslongAuthor Commented:
that works perfect!, could you do my one flavor and comment in some stuff to explain how it works?
0
 
Geert GruwezOracle dbaCommented:
ok,
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ContNrs;
 
type
  TNamedStringList = class(TStringList)
  private
    fName: string;
  published
  public
    constructor Create(aName: string); reintroduce;
    property Name: string read fName;
  end;
 
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    fSList: TObjectList;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
{ TNamedStringList }
 
constructor TNamedStringList.Create(aName: string);
begin
  // call TStringList constructor
  inherited Create;
  // set Name of object
  fName := aName;
end;
 
{ TForm1 }
 
constructor TForm1.Create(AOwner: TComponent);
begin
  // call TForm constructor
  inherited Create(AOwner);
  // Create container object to hold TStringLists
  // The container object is the owner of the TStringLists 
  fSList := TObjectList.Create(True);
end;
 
destructor TForm1.Destroy;
begin
  // Free the container object, the objects it owns are automatically freed too
  FreeAndNil(fSList);
  // Call the destructor of the form
  inherited Destroy;
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var item: TStringList;
  I: Integer;
begin
  // Find if the name is allready in use (non case sensitive)
  for I := 0 to fSList.Count - 1 do
    if SameText(TNamedStringList(fSList.Items[I]).Name, Edit1.Text) then
    begin
      ShowMessage('This name allready exists in the list');
      Exit;
    end;
  // Create a Named stringlist
  item := TNamedStringList.Create(Edit1.Text);
  // Add the items from the Listbox to the Stringlist
  item.AddStrings(ListBox1.Items);
  // Add the item to the container object
  fSList.Add(item);
end;
 
procedure TForm1.Button2Click(Sender: TObject);
var I: Integer;
  item: TNamedStringList;
begin
  // Start change (don't change display until finished)
  Memo1.Lines.BeginUpdate;
  try
    // Clear all entries
    Memo1.Lines.Clear;
    // Take each Stringlist from the container
    for I := 0 to fSList.Count - 1 do
    begin
      // Typecast the item to a usable TNamedStringList
      item := TNamedStringList(fSList.Items[I]);
      // Add the name to the memo
      Memo1.Lines.Add(item.Name);
      // Add the strings to the memo
      Memo1.Lines.AddStrings(item);
      // Add a blank line to the memo
      Memo1.Lines.Add('');
    end;
  finally
    // After changes, Update the display
    Memo1.Lines.EndUpdate;
  end;
end;
 
end.

Open in new window

0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
Geert GruwezOracle dbaCommented:
The trick is to use a container object,
this can hold anything descending from TObject
when you create it with AOwnsObjects = True then it will free the objects it contains on freeing the container

There is more types of containers in the unit ContNrs
0
 
jamerslongAuthor Commented:
Thanks, way more comments then expected. You save me from myself once again!
0
 
jamerslongAuthor Commented:
Ok, When i try to Edit a TNamed String List I get a Read address violation... a little help?
if exsists = true then
    else
      begin
      item := TNamedStringList.Create(ListBox1.Items.Strings[ListBox1.ItemIndex]);
      fSList.Add(item);
      end;
item := TNamedStringList(ListBox1.Items.Strings[ListBox1.ItemIndex]);
item.Clear;
for i := 0 to CheckListBox1.Items.Count -1 do
      begin
      If CheckListBox1.Checked[i] = true then
        begin
        item.Add(CheckListBox1.Items.Strings[i]);
        end
      end

Or also would would be better if i would Destroy the instance and remake it?
But i do need to know how to destory the instance if i do not need it anyore.
0
 
jamerslongAuthor Commented:
Nevermind, I got it!

for I := 0 to fSList.Count - 1 do
    if SameText(TNamedStringList(fSList.Items[I]).Name, ListBox1.Items.Strings[ListBox1.ItemIndex]) then
    begin
      item := TNamedStringList(fSList.Items[I]);
    end;
0
 
jamerslongAuthor Commented:
Allthough I still need to figure out how to delete an instance.
0
 
Geert GruwezOracle dbaCommented:
use the Remove function after using your search for finding the NamedStringList

function Remove(AObject: TObject): Integer;

if you set AOwnsObjects to true as i did, the stringlist is freed automatically
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

  • 5
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now