C++ / MFC: Loading resources by name (string)

All Windows resource handling APIs (like FindResource, LoadImage, LoadMenu,…) accept at least a resource identifier and an instance handle. This information is required to load the resource. MFC classes (like CMenu, CBitmap, …) only take the identifier as they try to find the module containing the resource on their own. This article discusses how you can load resources by ID (as integer and string) or name (string).

Say you create a menu resource called IDR_MENU_MAIN using Microfot Visual Studio. This will result in the following lines in the resource file:
// .rc file
IDR_MENU_MAIN MENU
BEGIN
   POPUP "File"
   BEGIN
    MENUITEM "Default Entry", ID_FILE_DOIT
    MENUITEM "Default Only Entry", ID_FILE_DEFAULTENTRY
   END
END

Visual Studio also adds a resource ID definition to the resource.h file:
//resource.h
#define IDR_MENU_MAIN 132

Given the appropriate instance handle, the new menu resource can now be easily loaded by its resource ID:
// .cpp file
HMENU hMenu = NULL;
HMODULE hModule = GetModuleHandle(NULL);
hMenu = ::LoadMenu( hModule, MAKEINTRESOURCE( IDR_MENU_MAIN ) );

Another way to load the resource would be to create a string that contains the resource ID preceded by a number sign (#):
HMENU hMenu = NULL;
HMODULE hModule = GetModuleHandle(NULL);
hMenu = ::LoadMenu( hModule, _T("#132") );

But how do you load the resource by its name? All of the resource APIs accept a resource name. But if you try the following you will get a ERROR_RESOURCE_NAME_NOT_FOUND (1814) error:
hMenu = ::LoadMenu( hModule, _T("IDR_MENU_MAIN") );

This happens as the RC file also includes the resource.h file and therefore the resource compiler replaces IDR_MENU_MAIN in the resource definition with 132. That means, that your menu resource is no longer named „IDR_MENU_MAIN“. Its now called „132“. You can use my utility program „DumpRes.exe“ to see how the resource compiler names your resources.

Putting a resource ID in quotes causes Visual Studio not to generate a resource ID.
Resource ID in quotes
To be able to load resources by their name you will have to remove the ID definition in the resource.h file. – By doing so you will not be able to reference the resource by its ID anymore… – If you use Visual Studio and create or modify a resource where you know that you will only be referencing it by name you can put the resource ID in quotes ( “ ) – This will cause Visual Studio not to create an ID in the resource.h file.

So… how would you use it?

Say you have an application that has to display a image resource depending on some external circumstance that is given as a string („OK“, „WARNING“, „FAIL“).

You embed three bitmaps in your resource file: „IDB_IMAGE_OK„, „IDB_IMAGE_WARNING„, „IDB_IMAGE_FAIL„. Please don’t forget to put the names in quotes.

In your code you build the string identifier of the image to display by concatenating the base name „IDB_IMAGE_“ with the status („OK“, „WARNING“, „FAIL“) and display it.
CString sImage = _T("IDB_IMAGE_") + m_sState ;
HBITMAP hBmp = (HBITMAP)LoadImage( GetModuleHandle(NULL), sImage, IMAGE_BITMAP, 32,32, LR_SHARED|LR_VGACOLOR );

Doing the same with resource IDs would require a ’switch‘ selection (if possible) or a mapping of states to resource ID.

By the way: the resource identifier string is case insensitive.🙂

3 Gedanken zu „C++ / MFC: Loading resources by name (string)

Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s