[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Index Out of Bounds

Posted on 2009-04-19
18
Medium Priority
?
699 Views
Last Modified: 2013-11-23
I have a form that displays several animated GIF's however, I am getting the attached errors when I execute the code below.  It works fine on another system, so I am thinking it may be a missing component but I am not sure.  Also it works on an MSSQL DB, but gives the Access Violation and Index out of bounds error when connected to Access.  Please advise.

Thanks,
aj85


procedure TForm1.FormCreate(Sender: TObject);
var
  BlobField : TBlobField;
  GIF : TGIFImage;
  MemStream : TMemoryStream;
  Picture : TPicture;
  T       : TStrings;
 
begin
  fIndexes := TList.Create;
  fGIFs := TObjectList.Create;
  MemStream := TMemoryStream.Create;
  T := TStringList.Create;
  try
    ADOTable1.Open;
    BlobField := TBLOBField(ADOTable1.FieldByName('Banners').AsString);
  //          S :=  ADOTable1.FieldByName('SiteLocation').AsString;
    while not ADOTable1.EOF do
      begin
       // S :=  ADOTable1.FieldByName('SiteLocation').AsString;
        MemStream.Clear;
        BlobField.SaveToStream(MemStream);
        MemStream.Seek(0, soFromBeginning);
        GIF := TGIFImage.Create;
        GIF.LoadFromStream(MemStream);
        fGIFs.Add(GIF);
        //T.Add(S);
 
        ADOTable1.Next;
      end;
  finally
    MemStream.Free;
  end;
  ADOTable1.Close;
end;

Open in new window

Error-Messages.doc
0
Comment
Question by:aj85
  • 9
  • 9
18 Comments
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 24180480
you get this AV when closing a connection to a database
and leave data aware components open.

next to that, you totally messed up on the try finally and levels of creating/destroying and control of flow

you should create a blobstream for each record and destroy after finishing the operation
procedure TForm1.FormCreate(Sender: TObject);
var
  BlobField : TBlobField;
  GIF : TGIFImage;
  MemStream : TMemoryStream;
  Picture : TPicture;
  T       : TStrings;
 
begin
  fIndexes := TList.Create;
  fGIFs := TObjectList.Create;
  MemStream := TMemoryStream.Create;
  try
    T := TStringList.Create;
    try
      ADOTable1.Open;
      //          S :=  ADOTable1.FieldByName('SiteLocation').AsString;
      while not ADOTable1.EOF do
      begin
       // S :=  ADOTable1.FieldByName('SiteLocation').AsString;
        MemStream.Clear;
        BlobField := TBLOBField(ADOTable1.FieldByName('Banners').AsString);
        try
          BlobField.SaveToStream(MemStream);
        finally
          FreeAndNil(BlobField);
        end;
        MemStream.Seek(0, soFromBeginning);
        GIF := TGIFImage.Create;
        GIF.LoadFromStream(MemStream);
        fGIFs.Add(GIF);
        //T.Add(S);
 
        ADOTable1.Next;
      end;
      ADOTable1.Close;
    finally
      FreeAndNil(T);
    end;
  finally
    MemStream.Free;
  end;
end;

Open in new window

0
 

Author Comment

by:aj85
ID: 24180664
Hello Geert,

I tried the code block that you added and I still get the same two errors.  First the AV on this line:

          BlobField.SaveToStream(MemStream);
Then the index out of bounds error after that.

Thanks,
aj85

0
 

Author Comment

by:aj85
ID: 24180688

Also when I hover over the "BlobField" in this line of code:

       BlobField := TBLOBField(ADOTable1.FieldByName('Banners').AsString);
              try

I see the following:

     BlobField = (FComponentStyle:[(out of bound)5..(out of bound)7])

Thanks,
aj85



 
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 24182018
you need ADOTable1.CreateBlobStream()
not BlobField
procedure TForm1.FormCreate(Sender: TObject);
var
  BlobStream : TBlobStream;
  GIF : TGIFImage;
  MemStream : TMemoryStream;
  Picture : TPicture;
  T       : TStrings;
 
begin
  fIndexes := TList.Create;
  fGIFs := TObjectList.Create;
  MemStream := TMemoryStream.Create;
  try
    T := TStringList.Create;
    try
      ADOTable1.Open;
      //          S :=  ADOTable1.FieldByName('SiteLocation').AsString;
      while not ADOTable1.EOF do
      begin
       // S :=  ADOTable1.FieldByName('SiteLocation').AsString;
        MemStream.Clear;
        BlobStream := ADOTable1.CreateBlobStream(AdoTable1.FieldByName('Banners'), bmRead);
        try
          MemStream.CopyFrom(BlobStream, BlobStream.Size);
        finally
          FreeAndNil(BlobStream);
        end;
        MemStream.Seek(0, soFromBeginning);
        GIF := TGIFImage.Create;
        GIF.LoadFromStream(MemStream);
        fGIFs.Add(GIF);
        //T.Add(S);
 
        ADOTable1.Next;
      end;
      ADOTable1.Close;
    finally
      FreeAndNil(T);
    end;
  finally
    MemStream.Free;
  end;
end;

Open in new window

0
 

Author Comment

by:aj85
ID: 24183745

When I execute this I get:  [Error] Unit1.pas(78): Undeclared identifier: 'TBlobStream'.
0
 
LVL 38

Accepted Solution

by:
Geert Gruwez earned 2000 total points
ID: 24183760
change this
  BlobStream : TBlobStream;
to
  BlobStream : TStream;
0
 

Author Comment

by:aj85
ID: 24183817
Perfect!  Can I ask a related question if I add 200 points to this?  In the animated GIF's I want to add a clickable link.  The line of code I am using is this:

 ShellExecute(Handle, 'Open', PChar(S), nil, nil, SW_SHOWNORMAL);

However the link that is passed in is different than the GIF that is showing so it goes to the wrong site.

aj85

0
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 24184786
i don't follow, you have an onclick event on the image component ?
0
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 24184813
i guess this is in correlation to your previous question ?

are you using the TGraphicStore ?
0
 

Author Comment

by:aj85
ID: 24185231
Hello,

Yes, that is correct the TGraphicStore.  What is happening is that the images are stored in the stream, but when they are displayed the URL that is assigned in the DB is not the one that opens.  The lines of code that assigns the value to "S" is commented out, becuase it continues to fail.

    //          S :=  ADOTable1.FieldByName('SiteLocation').AsString;
      while not ADOTable1.EOF do
      begin
       // S :=  ADOTable1.FieldByName('SiteLocation').AsString;

//T.Add(S);

When it gets to the shell execute line:

ShellExecute(Handle, 'Open', PChar(S), nil, nil, SW_SHOWNORMAL);

"S" may be the site location for image number1 although image number 3 is being show, or it may be the site location for image 3 although image number 2 is showing.  Hope this makes sense?j

Thanks,
aj85



0
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 24187199
you need to store all the information you want inside a object when you read from the database

you will need to create a container object for this:
do you understand the codesnippet below ?

the container should hold the image and all other information from that record ...
you then use the container later on instead of only the image
type
  TGifContainer = class(TObject)
  private
    fGif: TGifImage;
    fLink: string;
  public
    constructor Create;
    destructor Destroy; override;
    property Gif: TGifImage read fGif;
    property Link: string read fLink write fLink;
  end;
 
constructor TGifContainer.Create;
begin
  inherited Create;
  fGif := TGifImage.Create;
  fLink := '';
end;
 
destructor TGifContainer.Destroy;
begin
  FreeAndNil(fGif);
  inherited Destroy;
end;
 
procedure TForm1.FormCreate(Sender: TObject);
var
  BlobStream : TBlobStream;
  C: TGIFContainer;
  MemStream : TMemoryStream;
  Picture : TPicture;
  T       : TStrings;
begin
  fIndexes := TList.Create;
  fGIFs := TObjectList.Create;
  MemStream := TMemoryStream.Create;
  try
    T := TStringList.Create;
    try
      ADOTable1.Open;
      //          S :=  ADOTable1.FieldByName('SiteLocation').AsString;
      while not ADOTable1.EOF do
      begin
       // S :=  ADOTable1.FieldByName('SiteLocation').AsString;
        MemStream.Clear;
        BlobStream := ADOTable1.CreateBlobStream(AdoTable1.FieldByName('Banners'), bmRead);
        try
          MemStream.CopyFrom(BlobStream, BlobStream.Size);
        finally
          FreeAndNil(BlobStream);
        end;
        MemStream.Seek(0, soFromBeginning);
        C := TGIFContainer.Create;
        C.GIF.LoadFromStream(MemStream);
        C.Link := AdoTable1.FieldByName('SiteLocation').AsString;
        // Add more properties to C and save them here
        fGIFs.Add(C);
        ADOTable1.Next;
      end;
      ADOTable1.Close;
    finally
      FreeAndNil(T);
    end;
  finally
    MemStream.Free;
  end;
end;

Open in new window

0
 

Author Comment

by:aj85
ID: 24190587
Hello,

Ok now I am getting an AV when the image is displayed.  It is on a timer so I am attaching the code.

aj85

procedure TForm1.Timer1Timer(Sender: TObject);
var
  I, Index : Integer;
  TClick : String;
 
begin
  if fIndexes.Count = 0 then
    begin
      for I := 0 to fGIFs.Count - 1 do
   fIndexes.Add(pointer(I));
 
    end;
 
  Index := Random(fIndexes.Count);
  I := integer(fIndexes[Index]);
  fIndexes.Delete(Index);
  Image1.Picture.Assign(TGIFImage(fGIFs[I]));  //This line gives the AV.
  //S :=  ;
  if I = 0 then
  I := I + 1
  else
 ADOQuery1.Close;
 ADOQuery1.SQL.Clear;
 //ADOQuery1.SQL.CommaText := 'SELECT SITELOCATION FROM BANNERS WHERE ID =' + IntToStr(I) ;
 
 //S := ADOQuery1.FieldByName('SiteLocation').AsString;;
 
 end;

Open in new window

0
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 24190968
yeah, you should get the gif from inside the container ...

 Image1.Picture.Assign(TGIFImage(fGIFs[I].Gif));
0
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 24190969
you don't need to cast either ...

 Image1.Picture.Assign(fGIFs[I].Gif);
0
 

Author Comment

by:aj85
ID: 24195768
Hello,

When I add this line I get the following:

Image1.Picture.Assign(fGIFs[I].Gif);

[Error] Unit1.pas(221): Undeclared identifier: 'Gif'

aj85


0
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 24197768
lol, you will need to typecast to the container

 Image1.Picture.Assign(TGifContainer(fGIFs[I]).Gif);

I'm typing this in firefox and not testing this in Delphi, sorry about that.
0
 

Author Comment

by:aj85
ID: 24218643
Hello,

No problem. lol  That solved the issue, thanks alot.

aj85
0
 

Author Comment

by:aj85
ID: 24218721
Hello,

I could not increase the points on the questions, I am going to post a follow up question for the 200 points I indicated before.  Please reply and I will accept the answer, since you have answered it on this question.

Thanks,
aj85
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In our object-oriented world the class is a minimal unit, a brick for constructing our applications. It is an abstraction and we know well how to use it. In well-designed software we are not usually interested in knowing how objects look in memory. …
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
THe viewer will learn how to use NetBeans IDE 8.0 for Windows to perform CRUD operations on a MySql database.
Suggested Courses

872 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question