Jump to content


Check out our Community Blogs

Register and join over 40,000 other developers!


Recent Status Updates

View All Updates

Photo
- - - - -

Possible to tag a value onto a listbox item?

extract

  • Please log in to reply
12 replies to this topic

#13 Firebird_38

Firebird_38

    CC Addict

  • Advanced Member
  • PipPipPipPipPip
  • 117 posts

Posted 16 February 2010 - 01:58 PM

a staement like this:
Integer(Listbox1.Items.Objects[27]) will take the
Object pointer known as Listbox1.Items.Objects[27] and make the compiler see it as an Integer. Even though it is officially an object pointer, the compiler will now assume that it's really an integer. Basically you're overriding the standard type checking system and letting the compiler know that it doesn't know what it's talking about and that you know better. It's an integer, no matter how hard the compiler claims it's a pointer.
Typecasting is usually dangerous, since the compiler usually knows exactly what you can and cannot store in a variable or property. And what you're doing here is technically bad programming, but it makes things faster and uses less memory, as doing it the right way requires you to store pointers to objects, and those objects can contain whatever, but they are allocated in memory separately.

Again, the right way to do it is:
unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TThing=class
  private
    FMyOtherInfo: Integer;
    FMyInfo: String;
    procedure SetMyInfo(const Value: String);
    procedure SetMyOtherInfo(const Value: Integer);
  public
    constructor Create(StartInfo:String; StartOther:Integer);
    destructor Destroy; override;
    property MyInfo:String read FMyInfo write SetMyInfo;
    property MyOtherInfo:Integer read FMyOtherInfo write SetMyOtherInfo;
  end;
  TForm2 = class(TForm)
    ListBox1: TListBox;
  private
    { Private declarations }
  public
    { Public declarations }
    procedure AddThing(ItemName:String; ThingInfo:String; OtherInfo:Integer);
    procedure DeleteThing(ThingIndex:Integer); //first one is #0
    function GetThingFromItem(ThingIndex:Integer):TThing;
    procedure ReplaceThing(ThingIndex:Integer; NewThing:TThing);
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

{ TThing }

constructor TThing.Create(StartInfo: String; StartOther: Integer);
begin
 MyInfo:=StartInfo;
 MyOtherInfo:=StartOther;
end;

destructor TThing.Destroy;
begin
  //This is called when my "thing" is destroyed. We don't need
  //to do anything, though... If this "Thing" owned objects,
  //this is where they'd need to be freed.
  inherited;
end;

procedure TThing.SetMyInfo(const Value: String);
begin
  FMyInfo := Value;
end;

procedure TThing.SetMyOtherInfo(const Value: Integer);
begin
  FMyOtherInfo := Value;
end;

{ TForm2 }

procedure TForm2.AddThing(ItemName:String; ThingInfo: String; OtherInfo: Integer);
var NewThing:TThing;
begin
 NewThing:=TThing.Create(ThingInfo,OtherInfo);
 ListBox1.AddItem(ItemName,NewThing); //Adding 1 "thing" here, that has 2 properties of whatever kind
end;

procedure TForm2.DeleteThing(ThingIndex: Integer);
var OldThing:TThing;
begin
 ListBox1.Items.Objects[ThingIndex].Free;
 //I don't need to typecast this. That is because "Free" of TObject
 //always calls "Destroy". Since TThing.Destroy overrides the original
 //our destroy will get called.

 //Please be advised that the "thing" is still referenced here.
 //That can cause trouble, you can't use a non-existing object.
 //So, next we'll delete the item, and the reference with it.
 Listbox1.Items.Delete(ThingIndex);
end;

function TForm2.GetThingFromItem(ThingIndex: Integer): TThing;
begin
 result:=Listbox1.Items.Objects[ThingIndex] as TThing;
 //"as" does a safe typecast, by checking for type first and if it's
 //indeed a "thing", it will use that. Otherwise, however, it will
 //raise an exception. This should never happen here...

 //Please be advised that if you FREE or DESTROY the "thing"
 //returned here, the listbox will STILL point to the destroyed "thing".
 //When "DeleteThing" is called later, it will try to free it again, and
 //you can't destroy a non-existing object.
 //It might also, of course, be retrieved again using "GetThingFromItem"
 //or any other way, in which case it will still be just as invalid.
end;

procedure TForm2.ReplaceThing(ThingIndex: Integer; NewThing: TThing);
begin
 ListBox1.Items.Objects[ThingIndex].Free;
 //For a very, very short time, the listbox will now reference a
 //non-existing object.
 //Fix that here:
 ListBox1.Items.Objects[ThingIndex]:=NewThing;
end;

end.

This code does nothing by itself, and you'll need a listbox, but it's a nice setup. By wrapping the "add" and "delete", I made it safe to use.
  • 0





Also tagged with one or more of these keywords: extract

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download