T O P I C R E V I E W |
andyhill |
Posted - Dec 18 2012 : 23:40:34 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 |
10 L A T E S T R E P L I E S (Newest First) |
xequte |
Posted - Mar 24 2015 : 12:19:21 Thanks for the correction. I'll investigate when I am back in the office.
Nigel Xequte Software www.xequte.com nigel@xequte.com
|
codedcolor |
Posted - Mar 24 2015 : 06:00:35 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. |
xequte |
Posted - Jan 06 2013 : 22:06:44 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
|
andyhill |
Posted - Dec 23 2012 : 22:34:37 Fails
Andy |
xequte |
Posted - Dec 23 2012 : 21:41:12 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
|
andyhill |
Posted - Dec 22 2012 : 23:22:34 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 |
xequte |
Posted - Dec 22 2012 : 22:18:05 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
|
andyhill |
Posted - Dec 22 2012 : 12:16:33 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 |
xequte |
Posted - Dec 21 2012 : 15:03:44 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
|
w2m |
Posted - Dec 20 2012 : 12:35:10 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 |