代码如下:
procedure TForm1.FormCreate(Sender: TObject);
begin
Memo1.Lines[0] := 'This is the first line';
Memo1.Lines[1] := 'This is the second line';
ListBox1.Items[0] := 'first';
ListBox1.Items[1] := 'second';
end;procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.Lines.AddStrings(ListBox1.Items);
end;在我按下button1后出现异常,提示"list index out of bounds(0)"。在网上搜寻一番后找到解决方法是将"ListBox1.Items[0] := 'first';  ListBox1.Items[1] := 'second';"改为"ListBox1.Items.Add('first'); ListBox1.Items.Add('second');"。虽然问题解决了,却不知道其中的原因,用ListBox1.Items[0]和ListBox1.Items.Add不都是向listbox中加入字符串吗?它们之前有什么区别吗?请知道的详细解释下,谢谢!

解决方案 »

  1.   

    //这是Add方法的最后执行添加的方法,添加一个字符串,就分配一个TStringItem的结构;
    procedure TStringList.InsertItem(Index: Integer; const S: string; AObject: TObject);
    begin
      Changing;
      if FCount = FCapacity then Grow;
      if Index < FCount then 
        System.Move(FList^[Index], FList^[Index + 1],
          (FCount - Index) * SizeOf(TStringItem));
      with FList^[Index] do  //这里就是进行赋值
      begin
        Pointer(FString) := nil;
        FObject := AObject; //存的对象
        FString := S;牙//存的字符
      end;
      Inc(FCount);
      Changed;
    end;
    ///
    而你使用Items[0],实际上是调用,但是你没有使用Add方法添加进行去,所以在列表里找不到该项,所有会出错了。。
    function TStringList.Get(Index: Integer): string;
    begin
      if (Index < 0) or (Index >= FCount) then Error(@SListIndexError, Index);
      Result := FList^[Index].FString;
    end;
      

  2.   

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Memo1.Lines[0] := 'This is the first line';
    Memo1.Lines[1] := 'This is the second line';
    ListBox1.Items[0] := 'first';
    ListBox1.Items[1] := 'second';
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      showmessage(inttostr(ListBox1.ItemIndex));//你会发现显示的值为-1;说明
      Memo1.Lines.AddStrings(ListBox1.Items);   //ListBox1中没有项目
    end;
    Items[0] 是调用; 要想添加要用Add或AddObject...等
      

  3.   

    当然要改成这样才行了,ListBox1你要增加个节点才能往里面加数据呀,
    ListBox1.Items[0] := 'first';是往里面加数据,而你没有加节点,数据当然加不进去了,
    ListBox1.Items.Add('first');是新加个节点并把它赋值
      

  4.   

    楼主撒了一个谎吧,应该在按下button1之前错误就发生了。
      

  5.   

    楼主,对不起,错怪你了!经过试验,确实是在Button1被按下后才出的错,而且确实可以用 ListBox1.Items[0] := 'first' 赋值,只要下标不超过项数。(不过我发现Memo1不管下标是几,最后就只有第一行,可能跟实现方式有关,但跟本题无关,就没有深究下去)经过调试跟踪发现了原因:
    1、调用 ListBox1.Items[0] := 'first' 时,进行的操作是取出该行的 ItemData/Object 值,然后删除该项,再以新串插入原位置,然后恢复原来的 ItemData/Object 值。问题在这里,即使原来没有该项,在取ItemData值及删除时也都略了错误。使用的消息是 LB_SETITEMDATA 及 LB_GETITEMDATA 取的ItemData,LB_GETITEMDATA 在执行时如果有错则返回LB_ERR(-1),于是在恢复时也将该值放了回去。(源代码:TListBoxStrings.Put)
    如果 ListBox1.Items[i] 被赋值时超过了 ListBox1 的当前项数,则也会引发异常,不过错误信息为“Unable to insert a line”,太笼统了。我用下列方法
    if SendMessage(ListBox1.Handle, LB_INSERTSTRING, 2, Longint(PChar('line1'))) < 0 then
      ShowMessage( SysErrorMessage( GetLastError ) );
    得到精确的错误信息为:“无效索引”。2、在调用 Memo1.Lines.AddStrings(ListBox1.Items) 时,其中要取到 Objects[i] 的值,然后调用 AddObject 将串和Object给Memo1.Lines 。在取Objects[i]的值时,调用的是TListBoxStrings.GetObject方法,也是用 LB_GETITEMDATA 消息,但它检查了返回值,如果是LB_ERR(-1)是引发异常: if Longint(Result) = LB_ERR then Error(SListIndexError, Index) ,有点不分青红皂白(本来在1中正式存进去的就是-1,它应该检查一下GetLastError的值。谁说-1就不能是正确的值?这也是Windows API设计失败的一个地方——把错误号码跟返回值混杂一起)。(源代码:TStrings.AddStrings, TListBoxStrings.GetObject )3、如果调用的是 TListBox.Items.Add,那么它调用LB_ADDSTRING消息加入串,这时候 ItemData/Object 估计就默认为0/nil(我没有找到说明,但取出来确实是),于是 TListBoxStrings.GetObject 取出来时就不是LB_ERR(-1)而是0/nil了,因此不会出错。
      

  6.   

    纠正打字错误:使用的消息是 LB_SETITEMDATA 及 LB_GETITEMDATA 取的ItemData  =>  使用消息 LB_SETITEMDATA 及 LB_GETITEMDATA 来存取ItemData如果 ListBox1.Items[i] 被赋值时超过了 ListBox1 的当前项数  =>  如果 ListBox1.Items[i] 被赋值时i超过了 ListBox1 的当前项数(比如空是为i=1,有一项时为i=2)