FF2
FF2

Reputation: 85

Create and load resources in Delphi

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

Answers (1)

Remy Lebeau
Remy Lebeau

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

Related Questions