Thread: Resources

  1. #1
    Registered User
    Join Date
    Jan 2007
    Posts
    9

    Resources

    I am having great difficulty at using .rc files to access various .txt and .bmp files. I've searched extensively for tutorials but I have only find ones for C# (which I assume won't cross over).

    I wish to read and then display a bitmap from my .rc file using opengl (which I have managed to do when reading it from a file but I know nothing about resources) and to also place a .txt file in my .rc file and be able to access it as a string. My project compiles but I don't know how to access/use the resources.

    This is the only code I have in my .rc file:
    Code:
    MYIMAGEBMP BITMAP "myimage.bmp"
    So how would I access that from my code? And what do I need to add to this to include a .txt file? Does anyone know what I need to do, or if anyone knows of any good tutorials on resources that would be great.

    Thank you in advance.

    edit: I'm using the devcpp compiler in case that is of any particular relevance and i've managed to draw the bitmap using win32 (using LoadBitmap etc) but I wish to use opengl.

  2. #2
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    Code:
        HRSRC hrsrc = ::FindResource( NULL, MAKEINTRESOURCE(MYIMAGEBMP), TEXT("BITMAP") );
        HGLOBAL rsc = ::LoadResource( NULL, hrsrc );
        LPVOID lock = ::LockResource( rsc );
        DWORD size  = ::SizeofResource( NULL, hrsrc );
    Something like that. The lock will then be a just plain data pointer to that resource. You can also load it as a bitmap, like it is, with loadimage

    Code:
    HBITMAP hBmp = static_cast< HBITMAP > ( ::LoadImage( ::GetModuleHandle(0), MAKEINTRESOURCE(MYIMAGEBMP), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR ) );
    When you are finished with the hbitmap from the loadimage, you should use deleteobject on it. If you just want the raw data pointer, and used loadresource, you don't need to do anything. In 16-bit windows, there was unlockresource and freeresource but these are both useless now.

    To load a text file:

    Code:
    MYTEXTTHINGYMABOB BIN "mytextthingymabob.txt"
    You should have a resource.h file that looks like this:

    Code:
    #define MYIMAGEBMP 10001
    #define MYTEXTTHINGYMABOB 10002
    So that you can use the MAKEINTRESOURCE macro. There are also string tables which you might find to be of interest, and really once you know these things as basics, you just need a reference. http://msdn2.microsoft.com/en-au/library/aa381042.aspx I'd also look for the Resource Compiler User's Guide called RC.HLP

  3. #3
    Registered User
    Join Date
    Jan 2007
    Posts
    9
    Thank you very much, I think I'm getting there now but I am new to this so bare with me.

    First of all what variable type is the resource now stored in? Could I go about reading it in a similar way I would reading a .bmp file?

    And secondly your code;
    Code:
    MYTEXTTHINGYMABOB BIN "mytextthingymabob.txt"
    I notice that the "BIN" bit isn't in the list of resource definitions that i found on the site you linked (the list is http://msdn2.microsoft.com/en-au/library/aa381043.aspx). Perhaps STRINGTABLE would work better? But I don't understand this so I may be wrong.

    Thank you again.

  4. #4
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    It's actually something I made up

    User-Defined Resource

    nameID typeID [load-mem] filename
    The filename specifies the name of a file containing the binary data of the resource. The contents of the file are included as the resource. RC does not interpret the binary data in any way. It is the programmer's responsibility to ensure that the data is properly aligned for the target machine architecture.
    A user-defined resource can also be defined completely in the resource script using the syntax:
    nameID typeID [load-mem]
    BEGIN
    raw-data
    END
    A user-defined resource statement specifies a resource that contains application-specific data. The data can have any format and can be defined either as the content of a given file (if the filename parameter is given) or as a series of numbers and strings (if the raw-data block is given).

    Parameters

    nameID

    Specifies either a unique name or a 16-bit unsigned integer that identifies the resource.

    typeID

    Specifies either a unique name or a 16-bit unsigned integer that identifies the resource type. If a number is given, it must be greater than 255. The numbers 1 through 255 are reserved for existing and future redefined resource types.

    load-mem

    Specifies loading and memory attributes for the resource. For more information, see "Common Resource Attributes".

    filename

    Specifies the name of the file that contains the resource data. The parameter must be a valid filename; it must be a full path if the file is not in the current working directory.

    raw-data

    Specifies raw data consisting of one or more integers or strings of characters. Integers can be specified in decimal, octal, or hexadecimal format. RC does not automatically append a terminating null character to a string. The string is a sequence of the specified ANSI (byte) characters unless explicitly qualified as a wide-character string with the L prefix. Strings in all resources other than RCDATA and user-defined resources are Unicode strings.
    The block of data begins on a DWORD boundary and RC performs no padding or alignment of data within the raw-data block. It is the programmer's responsibility to ensure the proper alignment of data within the block.

    Example

    The following example shows several user-defined statements:

    array MYRES data.res
    14 300 custom.res
    18 MYRES2
    BEGIN
    "Here is a data string\0", /* A string. Note: explicitly
    null-terminated */
    1024, /* int */
    0x029a, /* hex int */
    0o733, /* octal int */
    "\07" /* octal byte */
    END
    Here's RC.HLP for the download. It'll only be around for 7 days so gettit while it's hot.

    http://download.yousendit.com/D5E25E3B2A962FA2

    So just note, to load that resource, with that custom typeId "BIN", I just do:

    Code:
        HRSRC hrsrc = ::FindResource( NULL, MAKEINTRESOURCE(MYTEXTTHINGYMABOB), TEXT("BIN") );
        HGLOBAL rsc = ::LoadResource( NULL, hrsrc );
        LPVOID lock = ::LockResource( rsc );
        DWORD size  = ::SizeofResource( NULL, hrsrc );
    Bling.

  5. #5
    Registered User
    Join Date
    Jan 2007
    Posts
    9
    Ok thanks, but I'm still not sure what kind of variable "lock" is pointing to. Is it a string? If I wanted to use the resource what would I have to do (lock-> ?)?

    You've been a great help so far, thanks again

  6. #6
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    If for example, we did have

    Code:
    HRSRC hrsrc = ::FindResource( NULL, MAKEINTRESOURCE(MYTEXTTHINGYMABOB), TEXT("BIN") );
    And

    Code:
    #define MYTEXTTHINGYMABOB 10001 /* whatever number */
    And

    Code:
    MYTEXTTHINGYMABOB  BIN "MYTEXTHINGY.TXT"
    And the contents of MYTEXTHINGY.TXT were

    Code:
    OH MY GOD, BECKY --
    Then you could say, after obtaining that lock

    Code:
    MessageBox[A]( HWND_DESKTOP, lock, lock, MB_OK );
    Because it just points right at that binary resource. Nothing special about that, just the binary data of the resource.

  7. #7
    Registered User
    Join Date
    Jan 2007
    Posts
    9
    I've just tried that and it didn't compile. I've set up the .rc and the .h file fine then I've added this code which is practically the same as yours:
    Code:
        HRSRC hrsrc = ::FindResource( NULL, MAKEINTRESOURCE(BRAINSLUGITXT), TEXT("BIN") );
        HGLOBAL rsc = ::LoadResource( NULL, hrsrc );
        LPVOID lock = ::LockResource( rsc );
        DWORD size  = ::SizeofResource( NULL, hrsrc );
        MessageBox( HWND_DESKTOP, lock, "", MB_OK );
    The compiler error is as follows:
    invalid conversion from 'void' to `const CHAR*'
    initializing argument 2 of `int MessageBoxA(HWND__*, const CHAR*, const CHAR*, UINT)'

    Thank you for your patience.

  8. #8
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    Code:
        MessageBox( HWND_DESKTOP, static_cast< LPCTSTR >( lock ), "", MB_OK );

  9. #9
    Registered User
    Join Date
    Jan 2007
    Posts
    9
    I'm afraid that that doesn't work, it compiles now but the message box is empty. I swapped the text - "static_cast< LPCTSTR >( lock )" - with the title - "" - and then it simply said error in the title (the .txt file contains ABC).

    edit: I've doubled checked that the .rc and the .h files were correct so it has to be this code - sorry.

  10. #10
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    You might check those function for failures. MSDN has details on what happens when they fail. So, BRAINSLUGITXT, eh. Are you consistent with that, as in, is that BRAINSLUGITXT identifier in your resource script and header?

  11. #11
    Registered User
    Join Date
    Jan 2007
    Posts
    9
    Sorry I changed that to a random .txt file a while ago that had writing in it, and i did change everything else for consistancy.

  12. #12
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    Well, see where the error occured.

    http://msdn.microsoft.com/library/de...oResources.asp

    All the functions are there. When you find which one failed, you can use GetLastError() to get the error code, and then look up what the problem is.

  13. #13
    Registered User
    Join Date
    Jan 2007
    Posts
    9
    It says on msdn that the title will be set to "Error" when it is given null. So I guess it may be your code - static_cast< LPCTSTR >( lock ) - could you tell me what it actually does? I'm guessing some kind of converstion. I'm hoping this isn't a too stupid question but like I said before I'm new to this.

  14. #14
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    It converts the void pointer into a string pointer.

    And for some reason, sometime even before that conversion, we never got the lock correctly. You should try to debug it and find which function failed, by checking for erraneous return values, and finding the reason with GetLastError()

  15. #15
    Registered User
    Join Date
    Jan 2007
    Posts
    9
    I'm still stuck (sadly ), and I'm having great problems getting GetLastError to show me the problem - it's also new to me.

    In my project I have main.cpp, resource.h and resources.rc.
    (Devcpp links resources.rc for me)

    Here is the code in resources.rc:
    Code:
    MYTXTFILE BIN "mytextfile.txt"
    Here is the code for resource.h:
    Code:
    #ifndef PROJECT1_RESOURCE_H
    #define PROJECT1_RESOURCE_H
    
    #define MYTXTFILE                  10001
    
    #endif
    And finally this is the code in main.cpp:
    Code:
    #include <windows.h>
    #include "Resource.h"
    
    int WINAPI WinMain (HINSTANCE hInstance,
                        HINSTANCE hPrevInstance,
                        LPSTR lpCmdLine,
                        int iCmdShow)
    {
        HMODULE hModule = GetModuleHandle(NULL);
        HRSRC hrsrc = ::FindResource( hModule, MAKEINTRESOURCE(MYTXTFILE), TEXT("BIN"));
        HGLOBAL rsc = ::LoadResource( NULL, hrsrc );
        LPVOID lock = ::LockResource( rsc );
        DWORD size  = ::SizeofResource( NULL, hrsrc );
        
        MessageBox( HWND_DESKTOP, (const char*) &lock, "", MB_OK );
        
        return 0;
    }
    No matter what I have tried I can't succeed at loading mytextfile.txt (which simply contains "ABC"). What am I doing wrong? I believe the problem is in FindResource because it always returns NULL (assuming it works fine up until then).

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Resources in Dev C++
    By JJFMJR in forum Windows Programming
    Replies: 7
    Last Post: 08-27-2007, 05:14 AM
  2. measuring system resources used by a function
    By Aran in forum C Programming
    Replies: 1
    Last Post: 03-13-2006, 05:35 PM
  3. Getting resources from another program.
    By Queatrix in forum C++ Programming
    Replies: 3
    Last Post: 02-11-2006, 09:00 PM
  4. Storing resources into a single file
    By LuckY in forum Game Programming
    Replies: 20
    Last Post: 08-14-2004, 11:28 PM
  5. Adding resources
    By nima_ranjbar in forum Windows Programming
    Replies: 0
    Last Post: 04-14-2002, 11:36 PM