Reputation: 85
Hi I have a program that when a button is loaded, creates a resource manually in the application itself (in this case an image) and then reads the resource to display in a timage.El problem is that it seems that creates the resource well but when I want load the resource says it can not find it when you are looking for.
The code.
procedure StringtoRes(const FileName: string; Inputstream: TMemoryStream);
var
hUpdate: THandle;
begin
hUpdate := BeginUpdateResource(PChar(FileName), True);
try
UpdateResource(hUpdate, RT_RCDATA, 'ID', LANG_NEUTRAL, Inputstream.Memory,
Inputstream.Size);
finally
EndUpdateResource(hUpdate, False);
end;
end;
procedure TForm1.btnTestClick(Sender: TObject);
var
MemStr: TMemoryStream;
FileName: string;
var
RStream: TResourceStream;
JPEGImage: TJPEGImage;
begin
FileName := 'c:/test/test.jpg';
MemStr := TMemoryStream.Create;
MemStr.LoadFromFile(FileName);
MemStr.Seek(0, soFromBeginning);
StringtoRes(paramstr(0), MemStr);
MemStr.Free;
Sleep(3000);
RStream := TResourceStream.Create(HInstance, 'ID', RT_RCDATA);
JPEGImage := TJPEGImage.Create;
JPEGImage.LoadFromStream(RStream);
Image1.Picture.Graphic := JPEGImage;
JPEGImage.Free;
RStream.Free;
end;
as I solve this?
Upvotes: 3
Views: 1712
Reputation: 596121
In general, a running process cannot update its own resources, as its executable file is locked and not writable. To do what you are attempting, you should move the resource to a separate DLL, then you can load the DLL dynamically via LoadLibrary()
when you need to load its resources, and unload it via FreeLibrary()
when you need to update its resources.
var
hResLib: THandle = 0;
procedure TForm1.btnTestClick(Sender: TObject);
var
ResFileName: string;
MemStr: TMemoryStream;
RStream: TResourceStream;
JPEGImage: TJPEGImage;
begin
ResFileName := ExtractFilePath(ParamStr(0)) + 'myres.dll';
if hResLib <> 0 then
begin
FreeLibrary(hResLib);
hResLib := 0;
end;
MemStr := TMemoryStream.Create;
try
MemStr.LoadFromFile('c:/test/test.jpg');
MemStr.Position := 0;
StringtoRes(ResFileName, MemStr);
finally
MemStr.Free;
end;
Sleep(3000);
hResLib := LoadLibrary(ResFileName);
Win32Check(hResLib <> 0);
RStream := TResourceStream.Create(hResLib, 'ID', RT_RCDATA);
try
JPEGImage := TJPEGImage.Create;
try
JPEGImage.LoadFromStream(RStream);
Image1.Picture.Graphic := JPEGImage;
finally
JPEGImage.Free;
end;
finally
RStream.Free;
end;
end;
Also, you are not checking the return value of BeginUpdateResource()
to make sure it is actually successful before then calling UpdateResource()
.
procedure StringtoRes(const FileName: string; Inputstream: TMemoryStream);
var
hUpdate: THandle;
bDiscard: BOOL;
begin
hUpdate := BeginUpdateResource(PChar(FileName), True);
Win32Check(hUpdate <> 0); // <-- ADD THIS!
bDiscard := True;
try
Win32Check(UpdateResource(hUpdate, RT_RCDATA, 'ID', LANG_NEUTRAL, Inputstream.Memory, Inputstream.Size));
bDiscard := False;
finally
EndUpdateResource(hUpdate, bDiscard);
end;
end;
Upvotes: 5