ImageEn for Delphi and C++ Builder ImageEn for Delphi and C++ Builder

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
Forum membership is Free!  Click Join to sign-up
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 ImageEnMView.ImageUserPointer as String
 New Topic  Reply to Topic
Author Previous Topic Topic Next Topic  

andyhill

Australia
133 Posts

Posted - Dec 18 2012 :  23:40:34  Show Profile  Reply
I have a need to store a custom string to each ThumbNail item in the ImageEnMView collection. Could some one please show me how to read and write this custom string:-

eg.

ImageEnMView0.ImageUserPointer[i]:= 'Hello World';

CustomString:= ImageEnMView0.ImageUserPointer[i];

Thanks in advance


Andy

w2m

USA
1990 Posts

Posted - Dec 20 2012 :  12:35:10  Show Profile  Reply
procedure TForm1.Button1Click(Sender: TObject);
var
  iInitialString: string;
  iCustomString: string;
begin
  if ImageEnMView1.SelectedImage <> -1 then
  begin
    iInitialString := 'This is a string assigned to ImageUserPointer';
    ImageEnMView1.ImageUserPointer[ImageEnMView1.SelectedImage] := @iInitialString;
    iCustomString := string(ImageEnMView1.ImageUserPointer[ImageEnMView1.SelectedImage]^);
    MessageBox(0, PWideChar(iCustomString), 'ImageEnMView ImageUserPointer To String',
      MB_ICONINFORMATION or MB_OK);
  end
  else
  begin
    MessageBox(0, 'Please select an image and try again.', 'No Selection', MB_ICONWARNING or
      MB_OK);
  end;
end;

William Miller
Email: w2m@frontiernet.net
EBook: http://www.imageen.com/ebook/
Apprehend: http://www.frontiernet.net/~w2m/index.html
Go to Top of Page

xequte

38611 Posts

Posted - Dec 21 2012 :  15:03:44  Show Profile  Reply
Hi Andy

If you are accessing the data in another procedure you will need to allocate the memory...


type
  TFileDataRecord = Record
    Description : string[100];
    ID : Byte;
  end;


var
  POurRecord : ^TFileDataRecord;
begin
  // Allocate memory
  GetMem(POurRecord, SizeOf(TFileDataRecord));

  iNewIndex := ImageEnMView1.AppendImage('C:\SomeImage.jpg');
  POurRecord.Description := 'West Island';
  POurRecord.ID := 101;

  ImageEnMView1.ImageUserPointer[iNewIndex] := POurRecord;
end;



Later when removing this item from the ImageEnMView1 ensure you deallocate the memory...

for i := 0 to ImageEnMView1.ImageCount - 1 do
  Dispose(ImageEnMView1.ImageUserPointer[i]);




Nigel
Xequte Software
www.xequte.com
nigel@xequte.com
Go to Top of Page

andyhill

Australia
133 Posts

Posted - Dec 22 2012 :  12:16:33  Show Profile  Reply
Thanks Nigel & Will.

I have implemented as follows (see Allocate, TidyUp, ReadCacheRecord, Move Failed:= [locks up]):-

type
  TCacheRecord = Record
    ID: Integer;
    FileName: String[255];
    Checked, Failed: Boolean;
  end;

procedure FetchThumbNails;
var
  PCacheRecord: ^TCacheRecord;
begin
  // Allocate memory
  GetMem(PCacheRecord, SizeOf(TCacheRecord));
  ...
  // Fetch ThumbNails
  for i:= 0 to FileNames.Count-1 do begin
    ...
    j:= ImageEnMView0.AppendImage;
    ImageEnMView0.SetImageFromStream(j, ms);
    ...
    // Add Cache Record
    PCacheRecord^.FileName:= FillSpace(255); // ReSet
    PCacheRecord^.FileName:= FileNames[i];
    PCacheRecord^.ID:= j;
    ImageEnMView0.ImageUserPointer[j]:= @PCacheRecord;
    ...
  end;
  ...
  // TidyUp
  Dispose(PCacheRecord);
end;

procedure ReadCacheRecord(idx: Integer);
var
  FileName: String;
begin
  ...
  FileName:= TCacheRecord(ImageEnMView0.ImageUserPointer[idx]^).FileName;
  ...
end;

procedure ImageEnMView0DestroyImage(Sender: TObject; idx: Integer);
begin
  Dispose(ImageEnMView0.ImageUserPointer[idx]);
end;

procedure Move(idx: Integer);
var
  FileName: String;
begin
  ...
  FileName:= TCacheRecord(ImageEnMView0.ImageUserPointer[idx]^).FileName;
  ...
  if MoveFile(PWideChar(FileName), PWideChar(Path+FileName)) = True then begin
    Dec(TotalCount);
    TFileDataRecord(ImageEnMView0.ImageUserPointer[i]^).Failed:= False;
  end else begin
    ...
  end;
  ...
end;


Andy
Go to Top of Page

xequte

38611 Posts

Posted - Dec 22 2012 :  22:18:05  Show Profile  Reply
Hi Andy

I'm sorry i haven't had time to test this, due to Xmas duties, but i think you would get some memory issues down the line, so please try as follows:

procedure FetchThumbNails;
var
PCacheRecord: ^TCacheRecord;
begin

// Fetch ThumbNails
for i:= 0 to FileNames.Count-1 do begin
...
j:= ImageEnMView0.AppendImage;
ImageEnMView0.SetImageFromStream(j, ms);


// Allocate memory for each file record
GetMem(PCacheRecord, SizeOf(TCacheRecord));
...
// Add Cache Record
PCacheRecord^.FileName:= FillSpace(255); // ReSet
PCacheRecord^.FileName:= FileNames[i];
PCacheRecord^.ID:= j;
ImageEnMView0.ImageUserPointer[j]:= @PCacheRecord;
...
end;
...
// Don't dispose of the record until we are finished with it (i.e. the file is no longer listed in the TImageEnMView)
// Dispose(PCacheRecord);
end;

Nigel
Xequte Software
www.xequte.com
nigel@xequte.com
Go to Top of Page

andyhill

Australia
133 Posts

Posted - Dec 22 2012 :  23:22:34  Show Profile  Reply
Implemented as suggested.

Will I have to walk the collection and delete one at a time (in order to fire ImageEnMView0DestroyImage [dispose]) or will ImageEnMView0.Clear take care of everything ?

Also can I read / write this way after creation and assignment:-

//
FileName:= TCacheRecord(ImageEnMView0.ImageUserPointer[i]^).FileName;
TCacheRecord(ImageEnMView0.ImageUserPointer[i]^).Failed:= False;
//

Above Locks Up plus FileName contains garbage.

Andy
Go to Top of Page

xequte

38611 Posts

Posted - Dec 23 2012 :  21:41:12  Show Profile  Reply
Hi Andy

Unfortunately ImageEnMView does not take care of the disposal of the memory, so you'll need to call Dispose() for each call you have to New() when you have finished using it (i.e. when clearing the ImageEnMView).

I cannot see why the following code:

FileName:= TCacheRecord(ImageEnMView0.ImageUserPointer[i]^).FileName;
TCacheRecord(ImageEnMView0.ImageUserPointer[i]^).Failed:= False;

Would cause any problem, but i can't test it until i am back in the office after Xmas.


If it is locking up it is possible you have already trashed the memory (was this created using New() and has not yet been disposed of?).

Try this way:

PCacheRecord := ImageEnMView0.ImageUserPointer[i];
Filename := PCacheRecord^.FileName;
PCacheRecord^.Failed:= False;



Nigel
Xequte Software
www.xequte.com
nigel@xequte.com
Go to Top of Page

andyhill

Australia
133 Posts

Posted - Dec 23 2012 :  22:34:37  Show Profile  Reply
Fails

Andy
Go to Top of Page

xequte

38611 Posts

Posted - Jan 06 2013 :  22:06:44  Show Profile  Reply
Here is one that i have tested:

type
  TFileDataRecord = Record
    Description : string[100];
    ID : Byte;
  end;


procedure TForm1.btnFillClick(Sender: TObject);
var
  POurRecord : ^TFileDataRecord;
  iNewIndex: Integer;
  i: Integer;
begin
  for i := 0 to ImageList.Count - 1 do
  begin
    // Allocate memory
    GetMem(POurRecord, SizeOf(TFileDataRecord));

    iNewIndex := ImageEnMView1.AppendImage(ImageList[i]);
    POurRecord.Description := 'West Island';
    POurRecord.ID := 101;

    ImageEnMView1.ImageUserPointer[iNewIndex] := POurRecord;
  end;
end;

procedure TForm1.btnShowInfoClick(Sender: TObject);
var
  POurRecord : ^TFileDataRecord;
begin
  if ImageEnMView1.SelectedImage < 0 then
    exit;

  POurRecord := ImageEnMView1.ImageUserPointer[ImageEnMView1.SelectedImage];
  ShowMessage(POurRecord.Description);
end;

procedure TForm1.ImageEnMView1DestroyImage(Sender: TObject; idx: Integer);
begin
  FreeMem(ImageEnMView1.ImageUserPointer[idx]);
end;


Nigel
Xequte Software
www.xequte.com
nigel@xequte.com
Go to Top of Page

codedcolor

Germany
8 Posts

Posted - Mar 24 2015 :  06:00:35  Show Profile  Reply
A pointer allocated with "GetMem" must be freed using "FreeMem". If you use "New" then you must use "Dispose". Don't use any other combination, that is going to fail sooner or later.

A typed pointer as in the example should be allocated using "New" and freed using "Dispose". Then you can also use a normal Unicode "string" in the record instead of the old string[100] type.
Go to Top of Page

xequte

38611 Posts

Posted - Mar 24 2015 :  12:19:21  Show Profile  Reply
Thanks for the correction. I'll investigate when I am back in the office.



Nigel
Xequte Software
www.xequte.com
nigel@xequte.com
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
Jump To: