0

添付ファイルを追加したいのですが、添付ファイルを追加するたびにフォームを長くして、ラベルといくつかの 16X16 画像を含む添付ファイルに関する情報を保持する行のためのスペースを空けます。このために、動的配列を使用することにしました (それが最適かどうかはわかりません)。添付ファイルが追加されるたびに、これらのオブジェクトの新しいインスタンスを作成したいと考えています。私のコードは機能していないようです。次のコードの何が問題になっていますか?

procedure TVisionMail.AddAttachment(FileString: String);
var
I: Integer;
begin
     AttCount := AttCount + 1; // increment attachment count

     //set attachment file name
     if (AttCount <> 0) and (edAttachment.Text <> '') then
       edAttachment.text := edAttachment.text + ';';
     edAttachment.text := edAttachment.text + FileString;

     //move objects position down to allow space for attachment line
     VisionMail.Height := VisionMail.Height + 25;
     Panel1.Height     := Panel1.Height + 25;
     btnSend.Top       := btnSend.Top + 25;
     btnExit.Top       := btnExit.Top + 25;
     StatusMemo.Top    := StatusMemo.Top + 25;
     Memo1.Top         := Memo1.Top + 25;
     lblBody.Top       := lblBody.Top + 25;

       //Allocate memory for arrays
       SetLength(newImg, AttCount);
       SetLength(newlbl, AttCount);
       SetLength(newDel, AttCount);
       SetLength(newPin, AttCount);

        //create new instance and set parents, positions, color, events
        newImg[AttCount]:= TImage.Create(VisionMail);
        with newImg[AttCount] do
        begin
              Parent     := Panel1;
              Top        := Memo1.Top - 25;
              Left       := 408;
              Height     := 16;
              Width      := 16;
        end;
        newlbl[AttCount]:= TLabel.Create(VisionMail);
        with newlbl[AttCount] do
        begin
              Parent     := Panel1;
              Top        := newImg[I].Top + 2;
              Left       := 397;
              Height     := 3;
              Width      := 13;
              BiDiMode   := bdRightToLeft;
       end;
       newDel[AttCount] := TAdvToolButton.Create(VisionMail);
       with newDel[AttCount] do
        begin
              Parent       := Panel1;
              Top          := newImg[I].Top;
              Left         := 440;
              Height       := 16;
              Width        := 16;
              color        := clBtnFace;
              colorChecked := clBtnFace;
              colorDown    := clBtnFace;
              colorHot     := clBtnFace;
              OnClick      := btnDelAttClick;
              OnMouseEnter := btnDelAttMouseEnter;
              OnMouseLeave := btnDelAttMouseLeave;
       end;
       newPin[AttCount] := TImage.Create(VisionMail);
       with newDel[AttCount] do
        begin
              Parent     := Panel1;
              Top        := newImg[I].Top;
              Left       := 425;
              Height     := 16;
              Width      := 16;
       end;
       //get Icon for extension of file
       lstIcons.GetBitmap(GetIcon(ExtractFileExt
                          (OpenDialog1.FileName)),
                          newImg[AttCount].Picture.Bitmap);
       newlbl[AttCount].Caption    := ExtractFileName(FileString);

end; 
4

1 に答える 1

1

最も明白な欠陥は、すべての配列の最後を書き留めていることです。たとえば、次のように記述します。

SetLength(newImg, AttCount);

これは、 の有効なインデックスnewImgが包括的であることを意味0します。AttCount-1しかし、あなたは書く

newImg[AttCount] := ...

最後のインデックスが であるため、これは境界外アクセスですAttCount-1。すべての配列アクセスに対して同じことを行います。

範囲チェックを有効にしてコンパイルすると、コンパイラは何が間違っているかを説明する実行時エラーを生成します。

個人的には、レコードを使用して 4 つのコンポーネントを保持する方がよいと思います。

TAttachmentControls = record
  Img: TImage;
  Lbl: TLabel;
  .. etc.
end;

そしてTList<TAttachmentControls>、コンテナとして a を使用します。

于 2013-02-26T11:10:14.140 に答える