3

I need to loop inside a resource file and and load all BMP files with the following statement; bBitmap.Handle := LoadBitmap(hInstance, 'IMAGE_NAME');

How do I loop a resource file; do I have to do a regular IO operation and treat it like a text file? I can read each line and create a list of bitmap names than on a separate loop execute the above statement to load bitmaps. Or is there a built-in method in Delphi libraries to do this operation?

FILE_NAME_1 BITMAP "btnFile1.bmp"
FILE_NAME_2 BITMAP "btnFile2.bmp"
....

Toby Allen
  • 10,997
  • 11
  • 73
  • 124
Alex
  • 367
  • 2
  • 4
  • 15
  • 2
    A resource is a binary chunk in the resource section inside the executable. There is no "resource file" once the executable is built, and it's definitely not text format. A "resource file" is a pre-compiled binary file that's linked into the executable when it's created; the resource file is created from source in a text "resource script" (unless it's pre-created as a binary file by the IDE). – Ken White Dec 03 '12 at 21:40
  • Well, you could hack it so the .RC file is included as the value of a constant in your app's code. Your app could then parse the constant, retrieve all image names and load them. Something like `const RC_CONTENTS = '''' {$INCLUDE MYRCFILE.RC} '''';` BUt you are probably gonna have to rename the .rc for this to work (or the res will be included twice) and you may find that getting the quotes right is gonna be a hassle if at all possible. – Marjan Venema Dec 03 '12 at 21:48
  • Thank you. I see that I have to pre-define values and use them. I will try to include the values as a constant as suggested by Marjan. At worst, I will probably create an array of strings. The list of images is long though. – Alex Dec 03 '12 at 22:01
  • 1
    XNResource Editior is AFAIK open source delphi. So it can list resources, you might find something there. – bummi Dec 03 '12 at 22:20
  • 3
    You can use the WinAPI function [EnumResourceNames](http://msdn.microsoft.com/en-us/library/windows/desktop/ms648037%28v=vs.85%29.aspx), which is what I suspect XNResource Editor uses to list them (as @bummi mentioned). I don't have a Delphi example handy, and a quick SO/MSDN search doesn't turn one up, though. – Ken White Dec 03 '12 at 22:43
  • There's an example in earlier Delphi versions (D007 and earlier, I think) called `ResXPlor` that might help. By default, it's in the public documents folder (`C:\Users\Public\Documents\RAD Studio\5.0\Demos\DelphiWin32\VCLWin32\resXplor` on Win7). – Ken White Dec 03 '12 at 22:46
  • @MarjanVenema please add your comment as an answer – Toby Allen Dec 03 '12 at 23:55
  • @TobyAllen: Thanks, but `EnumResourceNames` sounds like a much better option. – Marjan Venema Dec 04 '12 at 06:40

2 Answers2

5

I suggest you have a look at the Resource Explorer demo included with your Delphi installation. You can find it in "c:\Users\Public\Documents\RAD Studio\9.0\Samples\Delphi\VCL\resXplor\resxplor.dpr" (adjust for different path/Delphi version). In the ExeImage.pas file there are classes that allow you to easily assing the resources to TPicture etc.

Larsdk
  • 705
  • 6
  • 10
  • This is definitely related, example app loads resource names from the exe. I skimmed through code but didn't want to go through everything in there to find out what I needed. I've just googled the keyword EnumResourceNames to find info as suggested above. – Alex Dec 04 '12 at 17:25
2

EnumResourceNames as suggested by Ken White worked perfectly, and it's pretty simple to implement. Couldn't accept it as an answer because he left a comment only.

Here's my solution using the suggestion;

Inside the procedure where I load my images, I added the following lines of code;

var
  returnVal:bool;
  hMdl: HMODULE;
begin
  hMdl:=LoadLibraryEX('FileNameWithResources.exe',0,LOAD_LIBRARY_AS_DATAFILE);
  // I load bitmaps so RT_BITMAP parameter is chosen
  returnVal:=EnumResourceNames(hMdl,RT_BITMAP,@Callback,0);

@callback function returns a Boolean. You have to put this in the class level, before implementation code of the class. There's no declaration for it. My class is singleton so I call a class level procedure to add values to a TStringList. Do not return false if you have a more complex if statement and want to loop everything. If you return false at any time, calls to this function ends and you will not get rest of the resource names.

function Callback(handle:THandle;ResType:PChar;ResName:Pchar;long:Lparam):bool;stdcall;
var
      tempString: string;    
begin  
      tempString := resname;
      if length(tempString) > 0 then begin
        MyClassName.AddToResourceNames(tempString);
        result := true;
      end else
        result := false;
end;
Alex
  • 367
  • 2
  • 4
  • 15