Recent

Author Topic: casting integer to TObject for TStringList Objects array  (Read 33775 times)

MarcusM

  • New Member
  • *
  • Posts: 12
casting integer to TObject for TStringList Objects array
« on: November 13, 2010, 06:55:21 pm »
Hello, I am trying to store id (integer) values in the objects array of a TMemo's Lines property. However, when I access the values I always get '0' (zero) as the result.

See my simple example below. How do I access the integer values?

Code: [Select]
procedure TForm1.Button1Click(Sender: TObject);
begin
{Memo1 is a TMemo that I added to the form}
Memo1.Lines.Clear;
Memo1.Lines.AddObject('hello', TObject(1));
Memo1.Lines.AddObject('in', TObject(2));
Memo1.Lines.AddObject('there', TObject(3));
end;

procedure TForm1.Button2Click(Sender: TObject);
var
i: integer;
begin
for i := 0 to Memo1.Lines.Count - 1 do begin
ShowMessage(IntToStr(integer(Memo1.Lines.Objects[i])));
end;
end;

here are reference sites that I have found.
http://delphi.about.com/od/vclusing/a/items_addobject.htm
http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_26597662.html


Thanks in advance.

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: casting integer to TObject for TStringList Objects array
« Reply #1 on: November 13, 2010, 07:16:35 pm »
This works fine:

Code: [Select]
var
  sl :TStringList;

procedure TForm1.Button3Click(Sender: TObject);
begin
  sl := TStringList.Create;
  with sl do
  begin
    Clear;
    AddObject('hello', TObject(1));
    AddObject('in', TObject(2));
    AddObject('there', TObject(3));
  end;
end;

procedure TForm1.Button4Click(Sender: TObject);
var
i: integer;
begin
for i := 0 to sl.Count - 1 do begin
ShowMessage(IntToStr(integer(sl.Objects[i])));
end;

        sl.Free;
end;       

Why a TMemo?
« Last Edit: November 13, 2010, 07:19:51 pm by typo »

MarcusM

  • New Member
  • *
  • Posts: 12
Re: casting integer to TObject for TStringList Objects array
« Reply #2 on: November 14, 2010, 02:47:20 am »

Quote
Why a TMemo?

I am writing an application for me to categorize my reading notes. When the user (me) selects a tag or does a search a TMemo is populated with the notes associated with that action. Each note represents a single line. What I want to happen is that when a line(s) is selected, the popup menu can be initiated allowing to edit note(s), delete note(s), or modify associated tags. For this reason I need to associate the note id with the note string.

This should be my last hurdle to overcome before I can begin using the app. {I hope}

I now see an error in the subject of this post. TMemo.Lines is a TStrings not TStringList. Looking at the documentation though, TStrings should support this functionality.

Why does this not work with TMemo.Lines?


http://lazarus-ccr.sourceforge.net/docs/rtl/classes/tstrings.html


theo

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1927
Re: casting integer to TObject for TStringList Objects array
« Reply #3 on: November 14, 2010, 08:54:20 am »
Try TListBox instead of TMemo.

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: casting integer to TObject for TStringList Objects array
« Reply #4 on: November 14, 2010, 09:39:08 am »
Quote
Why does this not work with TMemo.Lines?

TMemo is a Windows control and nothing that happens in it has a reasonable explanation.

MarcusM

  • New Member
  • *
  • Posts: 12
Re: casting integer to TObject for TStringList Objects array
« Reply #5 on: November 14, 2010, 02:40:00 pm »
Quote
TMemo is a Windows control and nothing that happens in it has a reasonable explanation.

LOL, but really this is a bummer.

I do not want to use TListBox b/c I use TMemo in another spot for entering & editing the notes which has the same requirements for storing id's in the Objects array. There a text editor like interface is ideal. When viewing notes (as described above) it is desirable.

I am now trying to install TRichView.
« Last Edit: November 14, 2010, 02:56:06 pm by MarcusM »

theo

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1927
Re: casting integer to TObject for TStringList Objects array
« Reply #6 on: November 14, 2010, 03:26:57 pm »
LOL, but really this is a bummer.

I think what you want to do is a bit strange. A TMemo is not really "line based".
What if the user enters a new line or deletes the line ending (merges two or more lines)?
What happens to your objects then?

Not to talk about word-wrapping etc.
« Last Edit: November 14, 2010, 03:29:19 pm by theo »

ringo

  • New Member
  • *
  • Posts: 16
Re: casting integer to TObject for TStringList Objects array
« Reply #7 on: November 15, 2010, 05:32:04 am »
LOL, but really this is a bummer.

I think what you want to do is a bit strange. A TMemo is not really "line based".
What if the user enters a new line or deletes the line ending (merges two or more lines)?
What happens to your objects then?

Not to talk about word-wrapping etc.


None of that matters.  The Lines property in a TMemo has a TObject (a pointer) associated with each line.  If lines get merged or wrapped or whatever, it is up to the programmer to decide how to handle that.  The fact that a pointer is associated with each line means the programmer should be able to USE that pointer, even if it is only storing an integer value.

To the OP: can you stor a *real* TObject there, and get it back intact?

Ringo

ivan17

  • Full Member
  • ***
  • Posts: 173
Re: casting integer to TObject for TStringList Objects array
« Reply #8 on: November 15, 2010, 02:21:09 pm »
LOL, but really this is a bummer.
really? was it that hard to throw in an array or a TObjectList (i'd prefer an array) and be done with it instead of insisting on a memo.

by the way, i concur, don't use a memo.
and seriously dude, if everyone tells you don't use a memo for that then don't use a memo for that.

me, i'd make a multiline listbox and use a memo for editing single items inline.
the simplest option i'd recomend for you would be KGrid with just one column (see the main demo).

ringo

  • New Member
  • *
  • Posts: 16
Re: casting integer to TObject for TStringList Objects array
« Reply #9 on: November 15, 2010, 04:43:35 pm »
Two things:

First, this conversion in a TMemo.Lines.Objects to and from an integer works fine for me.  I just wrote a small test program to store an integer in the Objects
  • array, and convert it back to an integer;


The relevant code is:

procedure TForm1.FormCreate(Sender: TObject);
var
  i,n:  integer;
  s:    string;
begin
  for i := 0 to 6 do
    begin
    s := IntToStr(i);
    Memo1.Lines.Add(s);
    Memo1.Lines.Objects := TObject(i);
    end;

  s := '';
  for i := 0 to 6 do
    begin
    n := integer(Memo1.Lines.Objects);
    s := s + IntToStr(n) + ', ';
    end;
  Memo1.Lines.Add(s);
end;     


Worked with no problems.

Second item: why do some people insist on telling other people "don't do that"? Are they politicians or something?  Perhaps the "code police"?

If somebody is using a particular construct, he/she usually has a good reason.  If they don't have a good reason, they'll ask for suggestions for a better component or construction.  Telling somebody "don't do that" is just a cheap way to say "I don't know what's wrong".

Ringo




ringo

  • New Member
  • *
  • Posts: 16
Re: casting integer to TObject for TStringList Objects array
« Reply #10 on: November 15, 2010, 04:48:08 pm »
Actually, the editor seemed to have "interpreted" my code sample; here it is again, hopefully without interpretation:


procedure TForm1.FormCreate(Sender: TObject);
var
  i,n:  integer;
  s:    string;
begin
  for i := 0 to 6 do
    begin
    s := IntToStr(i);
    Memo1.Lines.Add(s);
    Memo1.Lines.Objects[ i ] := TObject(i);
    end;

  s := '';
  for i := 0 to 6 do
    begin
    n := integer(Memo1.Lines.Objects[ i ]);
    s := s + IntToStr(n) + ', ';
    end;
  Memo1.Lines.Add(s);
end;             


Ringo

MarcusM

  • New Member
  • *
  • Posts: 12
Re: casting integer to TObject for TStringList Objects array
« Reply #11 on: November 17, 2010, 01:46:02 pm »
Thanks Ringo. You're approach had me excited. Unfortunately, it only works when accessing the objects within the function they were added. The following does not work:

Code: [Select]
procedure TForm1.FormCreate(Sender: TObject);
var
  i: integer;
  s: string;
begin
  for i := 0 to 6 do begin
    s := IntToStr(i);
    Memo1.Lines.Add(s);
    Memo1.Lines.Objects[i] := TObject(i);
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  i, n: integer;
  s: string;
begin
  s := '';
  for i := 0 to 6 do begin
    n := integer(Memo1.Lines.Objects[i]);
    s := s + IntToStr(n) + ', ';
  end;
  Memo1.Lines.Add(s);
end;

MarcusM

  • New Member
  • *
  • Posts: 12
Re: casting integer to TObject for TStringList Objects array
« Reply #12 on: November 17, 2010, 02:09:53 pm »

Quote
the simplest option i'd recomend for you would be KGrid with just one column (see the main demo).

Though I'm confident that if TMemo.Lines handled the Objects array as expected my app would work as I envisioned, KGrid looks like a potential alternative. However, I can't get Lazarus to install new components {I've got another thread going for that problem}.



Quote
can you stor a *real* TObject there, and get it back intact?

No, this doesn't work either. It prompts 'Access Violation', guessing that's because nothing is in the Object array.


Code: [Select]
procedure TForm1.btnAdd1Click(Sender: TObject);
var
  btn: TButton;
begin
  btn := TButton.Create(Form1);
  Memo1.Lines.Clear;
  Memo1.Lines.Add('hello');
  Memo1.Lines.Objects[0] := TObject(btn);
end;

procedure TForm1.btnShow1Click(Sender: TObject);
var
  btn: TButton;
begin
 try
    ShowMessage(Memo1.Lines.Objects[0].ClassName);
  except on e: Exception do begin
    ShowMessage(e.Message);
    end;
  end;
end;

ringo

  • New Member
  • *
  • Posts: 16
Re: casting integer to TObject for TStringList Objects array
« Reply #13 on: November 17, 2010, 05:04:02 pm »
I looked through the source code for TStrings and TStringList, and I found that TStrings actually does NOT implement the Objects array.  There are dummy functions there (with the virtual attribute) that are meant to be over-ridden by descendant classes.

Class TStringList does implement the Objects array, so the example code above will work correctly.

However, since TMemo uses TStrings instead of TStringList, the assignment to/from an integer will not work correctly.

This does not seem to be a correct implementation of TStrings.  The original Delphi version of TStrings implements the Objects array (and is then inherited by TStringList).

I am not sure, but does this qualify as a "bug" in TStrings?

Ringo

ivan17

  • Full Member
  • ***
  • Posts: 173
Re: casting integer to TObject for TStringList Objects array
« Reply #14 on: November 17, 2010, 08:33:40 pm »
However, since TMemo uses TStrings instead of TStringList, the assignment to/from an integer will not work correctly.
no, memo uses TMemoStrings, simpler descendant of TStrings.  TStrings itself is never directly used by anyone as it simply can not be used (it is an abstract class). it is used only as a placeholder for objects of descendant classes.

However, since
I am not sure, but does this qualify as a "bug" in TStrings?
not in my book.

Though I'm confident that if TMemo.Lines handled the Objects array as expected my app would work as I envisioned...
did you envision a label above the memo (large red font) saying "please don't
delete lines 2-5 in the input box below"?

However, I can't get Lazarus to install new components
let me check: open kgridlaz.lpk; click compile; nice; click install; wait; wait; wait; done; try - works (laz0.9.29, win32)
i can send you the zip file (1,166,784 bytes) - pm me with mail.

 

TinyPortal © 2005-2018