Visit our Sponsor   Visit our Sponsor
delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
496 Users Online NOW
Have a look at your member-status

connecting people's knowledge


  - Recent ArticlesRSS feed for Recent Articles on delphi3000.com
  - List of All Articles
  - Top Viewed Articles
  - Articles (+Attachem.)
  - Articles Of Interest
  - Categories
  - Top Uploader
  - Search
  - Index

  - My Home
  - Submit an Article
  - My Articles
  - My Personal Data
  - My Bookmarks
  - Activities
  - Login/Logout

  - Sign Up
  - Why Sign Up
  - Newsletter

  - Press
  - Advertise

  - Contact
  - Feedback





Community
Borland
ClubeDelphi
Dr. Bob
UK-BUG
Delphi Meetings
Planeta Delphi



Loremo - the 1.5 liter car coming in 2009




Startblatt.de






Share this article with friendsShare this article with friends
Rate this articleRate this article - to keep the quality of delphi3000.com !
Comment this article or read through previous comments (0)


Using TList's and Pointers in delphi (Part II)Component available for this articleFormat this article printer-friendly!Bookmark function is only available for registered users!
Product:
Delphi all versions
Category:
OO-related
Skill Level:
Scoring:
Last Update:
09/12/2003
Search Keys:
delphi delphi3000 article borland vcl code-snippet delphi Tlist pointers helper-class record dynamic
Times Scored:
7
Visits:
7975
Uploader: Stewart Moss
Company: New Heights Software Developme
Reference: http://www.delphi3000.com/articles/article_3705.asp
Component Download: http://www.new-heights.co.za/Delphi/TList Record Example.zip
 
Question/Problem/Abstract:
This is a nice demonstration of how to create records on a TList object.

It creates and manages a list of Pointers to TMammal record instances.
Answer:




{-----------------------------------------------------------------------------
Unit Name: Unit1

Creation Date: 10-September-2003  22:12:59
Documentation Date: 10-September-2003  22:12:59
Version: 1.0

Keywords: Generic, Tlist, Pointers

Description:

  This is a demonstration of how to create records on a TList object.

  It creates a list of Pointers to TMammal record instances.

  TMammal = record
    TType: string;
    Hair: string;
    speak: string;
  end;

  Note the Speak element in this record.
  In a later demo I will show how to do this with objects stored on a TList.

  The TType is either "Human" or "Dog"

  Integers but they could be a list of pointers
  to any record or class type.

  At the end of this is the source for the DFM file used to run this application.
  (It just needs to be bound into a project)

Notes:
  If there are any terms or concepts in this demo you don't understand please
  ask me.

Dependancies:

Compiler version:

History:

          Copyright 2003 by Stewart Moss
          All rights reserved.
-----------------------------------------------------------------------------}

unit Unit1;

interface

uses
  
Windows, Messages, sysutils, Variants, classes, Graphics, Controls, forms,
  
Dialogs, StdCtrls;

type
  
PMammal = ^TMammal;
  
TMammal = record
    
TType: string;
    
Hair: string;
    
speak: string;
  
end;

  
TForm1 = class(TForm)
    
btnAdd: TButton;
    
btnDelete: TButton;
    
ListBox1: TListBox;
    
Button1: TButton;
    
GroupBox1: TGroupBox;
    
Label1: TLabel;
    
Label2: TLabel;
    
lblType: TLabel;
    
Label4: TLabel;
    
lblSpeak: TLabel;
    
lblHair: TLabel;
    
Label7: TLabel;
    
Button2: TButton;
    
Label3: TLabel;
    
lblIndex: TLabel;
    
Button3: TButton;
    
procedure FormCreate(Sender: TObject);
    
procedure FormClose(Sender: TObject; var Action: TCloseAction);
    
procedure btnAddClick(Sender: TObject);
    
procedure btnDeleteClick(Sender: TObject);
    
procedure Button1Click(Sender: TObject);
    
procedure ListBox1Click(Sender: TObject);
    
procedure Button2Click(Sender: TObject);
    
procedure Button3Click(Sender: TObject);
  
private
    
{ Private declarations }

    
MammalList: TList;

    
function FindMammalByIndex(Index: integer): PMammal;
    
procedure FreeList;
    
procedure showlist;
    
procedure DeleteMammalAtIndex(Index: integer);
    
procedure ClearGroupBox;

  
public
    function
GetRandomHair: string;
    
{ Public declarations }
  
end;

var
  
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  
MammalList := TList.create;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  
FreeList;
  
MammalList.Free;
end;

procedure TForm1.FreeList;
{-----------------------------------------------------------------------------
  Procedure: TForm1.FreeList
  Author:    Stewart Moss
  Date:      20-Jan-2003

    This disposes of all the existing items in the list.

    ** Very important you can't just free the TList object and expect **
    ** everything else to disappear                                   **

    This is optimized to always delete the last item on the list.
    It gives the memory manager less work to do!
    * tx delphi300.com :)
-----------------------------------------------------------------------------}
var
  
loop: integer;
  
tmpcount: integer;
begin
  
tmpcount := MammalList.Count - 1;

  
for loop := tmpcount downto 0 do
  begin
    
dispose(MammalList.Items[loop]);
    
MammalList.Delete(loop);
  
end;

end;

procedure TForm1.btnAddClick(Sender: TObject);
{-----------------------------------------------------------------------------
  Procedure: TForm1.btnAddClick
  Arguments: Sender: TObject
  Result:    None

  Date:      10-September-2003  22:19:22

Description:
        Creates a new record and stores it in the Pointer Reference "APMammal".

        One of the benifits of using objects is you don't have to know how
        big the object is to create it.

      Copyright 2003 by Stewart Moss
      All rights reserved.
-----------------------------------------------------------------------------}
var
  
APMammal: PMammal;
begin
  
randomize;                            // hehehe

  // Create and assign memory to a new TMammal record and store it's pointer

  
new(APMammal);

  
// Now we choose a random dog or human and set the values

  
with APMammal^ do
  begin
    case
random(2) of
      
0:                                // Human
        
begin
          
// if it wasn't for "with APMammal^ do" then these
          // lines would read.
          // APMammal^.TType := 'Human';
          // APMammal^.Hair := 'Blonde';
          // APMammal^.speak := 'Hello!';
          //
          // "APMammal^." is called "dereferencing the pointer"
          //
          // You are basically saying:
          // set (or get) the value of the item (eg Hair) at the pointer
          // address held in APMammal.

          
TType := 'Human';
          
Hair := GetRandomHair;
          
speak := 'Hello!';
        
end;
      
1:                                // Dog
        
begin
          
TType := 'Dog';
          
Hair := GetRandomHair;
          
speak := 'Woof Woof!';
        
end;
    
end;                                // case
  
end;                                  // with

  // Now add this pointer to the TList
  // This returns the index position of the item (ie where it is added to the list)
  // We don't need it.
  //
  // More correct is
  // Indexpos := MammalList.add(APMammal);
  
MammalList.add(APMammal);

  
showlist;
end;

procedure TForm1.showlist;
{-----------------------------------------------------------------------------
  Procedure: TForm1.showlist
  Author:    Stewart Moss
  Date:      20-Jan-2003

    PInteger(MammalList.Items[loop])^ returns the integer value stored at the
    Integer Pointer in the List (de-reference).

    Note:
     This time I have "type-casted" the generic pointer. I have
     prefered not to use a temporary variable called "APMammal" again.

     This saves on memory management when accessing more than one property.

An in-efficient (but clearer) method is

var
  loop: integer;
  APMammal:PMammal;
begin
  ListBox1.Items.Clear;
  for loop := 0 to MammalList.Count - 1 do
  begin
    APMammal := PMammal(MammalList.Items[loop])^;
    ListBox1.Items.add(IntTostr(loop) + ' -> ' + PMammal(APMamal.TType);
  end;
end;

-----------------------------------------------------------------------------}
var
  
loop: integer;
begin
  try                                  
// cheap trick to swallow un-wanted exceptions

    
ListBox1.Items.Clear;
    
for loop := 0 to MammalList.Count - 1 do
    begin
      
ListBox1.Items.add(IntTostr(loop) + ' -> ' +
        
PMammal(MammalList.Items[loop])^.TType);
    
end;                                // for

    // Select the last item in the TList
    
ListBox1.ItemIndex := ListBox1.Items.Count - 1;

    
// Call the Listbox1 click event, to update the groupbox by retreiving the record
    // from the list

    
ListBox1Click(Self);

  
except                                // See I don't trap anything here:
    // clear the group box
    
ClearGroupBox;
  
end;                                  // I have been a bad boy!
end;

procedure TForm1.btnDeleteClick(Sender: TObject);
var
  
tmpstr: string;
  
tmpint: integer;
begin

  
// User has to enter the index of the item to delete (ie remove from the list)
  
tmpstr := Inputbox('Delete an item out of the list',
    
'Which item do you want to delete (0=first) ?', '');

  
if tmpstr = '' then
    
Exit;

  
try
    
tmpint := StrToInt(Trim(tmpstr));
  
except
    raise
exception.create(tmpstr + ' is not an integer!');
  
end;

  
// Now delete it
  
DeleteMammalAtIndex(tmpint);

  
showlist;

  
//  showmessage('Deleted Item Index ' + IntTostr(Index));
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  
showlist;
end;

function TForm1.FindMammalByIndex(Index: integer): PMammal;
(*-----------------------------------------------------------------------------
  Procedure: TForm1.FindMammalByIndex
  Arguments: Index: integer

  Date:      10-September-2003  22:41:35

  Description:
        This returns the TMammal record stored at position Index
        in the TList.

        It traps any exceptions caused by selecting records out of range.

      Copyright 2003 by Stewart Moss
      All rights reserved.
-----------------------------------------------------------------------------*)
begin
  
// Turn on the range exception
  {R+}
  
try
    
result := PMammal(MammalList.Items[Index]);
  
except
    on
e: ERangeError do
    begin
      raise
exception.create('Cannot retrieve record at position ' + IntTostr(Index));
    
end;
  
end;
{$R-}
end;

procedure TForm1.ListBox1Click(Sender: TObject);
var
  
APMammal: PMammal;
begin

  
// Find the currently selected Index in the Listbox.
  // And use this to point to the TList
  
APMammal := FindMammalByIndex(ListBox1.ItemIndex);

  
with APMammal^ do
  begin
    
lblType.caption := TType;
    
lblHair.caption := Hair;
    
lblSpeak.caption := speak;
    
lblIndex.caption := IntTostr(ListBox1.ItemIndex);
  
end;                                  // with

end;

function TForm1.GetRandomHair: string;

begin
  case
random(5) of
    
0: result := 'Blonde';
    
1: result := 'Brown';
    
2: result := 'Blue';
    
3: result := 'Black';
    
4: result := 'Red';
  
end;                                  // case
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  
Close;
end;

procedure TForm1.DeleteMammalAtIndex(Index: integer);
begin
  if
Index > MammalList.Count - 1 then
    raise
exception.create('Number too high!');

  
dispose(MammalList.Items[Index]);     // Free it's memory
  
MammalList.Delete(Index);             // and remove from list
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  try
    
DeleteMammalAtIndex(ListBox1.ItemIndex);
    
showlist;
  
except
    
// clear the group box
    
ClearGroupBox;
  
end;
end;

procedure TForm1.ClearGroupBox;
begin
  
lblType.caption := '<none>';
  
lblHair.caption := '<none>';
  
lblSpeak.caption := '<none>';
  
lblIndex.caption := '<none>';
end;

end.


{
Unit1.DFM
----------


object Form1: TForm1
  Left = 168
  Top = 106
  Width = 284
  Height = 412
  Caption = 'Stewart Moss TList Example II'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  OnClose = FormClose
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 24
    Top = 12
    Width = 193
    Height = 13
    Caption = 'Nice and dirty record TList demonstration'
  end
  object btnAdd: TButton
    Left = 24
    Top = 61
    Width = 75
    Height = 25
    Caption = 'Add'
    TabOrder = 0
    OnClick = btnAddClick
  end
  object btnDelete: TButton
    Left = 104
    Top = 31
    Width = 75
    Height = 25
    Caption = 'Delete Prompt'
    TabOrder = 1
    OnClick = btnDeleteClick
  end
  object ListBox1: TListBox
    Left = 28
    Top = 92
    Width = 217
    Height = 109
    ItemHeight = 13
    TabOrder = 2
    OnClick = ListBox1Click
  end
  object Button1: TButton
    Left = 184
    Top = 61
    Width = 75
    Height = 25
    Caption = 'Refresh'
    TabOrder = 3
    OnClick = Button1Click
  end
  object GroupBox1: TGroupBox
    Left = 24
    Top = 208
    Width = 221
    Height = 137
    Caption = ' Object Properties '
    TabOrder = 4
    object Label2: TLabel
      Left = 53
      Top = 50
      Width = 24
      Height = 13
      Caption = 'Type'
    end
    object lblType: TLabel
      Left = 105
      Top = 50
      Width = 36
      Height = 13
      Caption = '<none>'
    end
    object Label4: TLabel
      Left = 50
      Top = 74
      Width = 31
      Height = 13
      Caption = 'Speak'
    end
    object lblSpeak: TLabel
      Left = 105
      Top = 74
      Width = 36
      Height = 13
      Caption = '<none>'
    end
    object lblHair: TLabel
      Left = 105
      Top = 98
      Width = 36
      Height = 13
      Caption = '<none>'
    end
    object Label7: TLabel
      Left = 39
      Top = 98
      Width = 52
      Height = 13
      Caption = 'Hair Colour'
    end
    object Label3: TLabel
      Left = 52
      Top = 26
      Width = 26
      Height = 13
      Caption = 'Index'
    end
    object lblIndex: TLabel
      Left = 105
      Top = 26
      Width = 36
      Height = 13
      Caption = '<none>'
    end
  end
  object Button2: TButton
    Left = 196
    Top = 352
    Width = 75
    Height = 25
    Caption = 'E&xit'
    TabOrder = 5
    OnClick = Button2Click
  end
  object Button3: TButton
    Left = 105
    Top = 61
    Width = 75
    Height = 25
    Caption = 'Delete'
    TabOrder = 6
    OnClick = Button3Click
  end
end

}







Please rate this article!
Skill level:
BeginnerExpert

Useful:
No!Very!

Overall rating:
PoorExcellent



Comments to this article
Write a new comment













 
Sign up to consume product discounts for Bronze memberships !

read more


  Visit our Sponsor

 

  Community Ad of
I. Siticov
 
   














 







     
  Copyright © 2000 - 2007 delphi3000.com - All rights reserved. Terms of use. || Privacy
delphi3000.com is a service by bluestep.com IT-Services GmbH (Vienna)