Tipos de recursos

A continuación se muestran los tipos de recursos predefinidos.

Constant/value Description
RT_ACCELERATOR
MAKEINTRESOURCE(9)
Tabla aceleradora.
RT_ANICURSOR
MAKEINTRESOURCE(21)
Cursor animado.
RT_ANIICON
MAKEINTRESOURCE(22)
Icono animado.
RT_BITMAP
MAKEINTRESOURCE(2)
Recurso de mapa de bits.
RT_CURSOR
MAKEINTRESOURCE(1)
Recurso de cursor dependiente del hardware.
RT_DIALOG
MAKEINTRESOURCE(5)
Cuadro de diálogo.
RT_DLGINCLUDE
MAKEINTRESOURCE(17)
Permite que una herramienta de edición de recursos asocie una cadena a un archivo .rc. Normalmente, la cadena es el nombre del archivo de encabezado que proporciona nombres simbólicos. El compilador de recursos analiza la cadena, pero de lo contrario omite el valor. Por ejemplo:
1 DLGINCLUDE "MyFile.h"
RT_FONT
MAKEINTRESOURCE(8)
Recurso de fuente.
RT_FONTDIR
MAKEINTRESOURCE(7)
Recurso de directorio de fuentes.
RT_GROUP_CURSOR
MAKEINTRESOURCE((ULONG_PTR)(RT_CURSOR) + 11)
Recurso de cursor independiente del hardware.
RT_GROUP_ICON
MAKEINTRESOURCE((ULONG_PTR)(RT_ICON) + 11)
Recurso de icono independiente del hardware.
RT_HTML
MAKEINTRESOURCE(23)
Recurso HTML.
RT_ICON
MAKEINTRESOURCE(3)
Recurso de icono dependiente del hardware.
RT_MANIFEST
MAKEINTRESOURCE(24)
Manifiesto de ensamblado en paralelo.
RT_MENU
MAKEINTRESOURCE(4)
Recurso de menú.
RT_MESSAGETABLE
MAKEINTRESOURCE(11)
Entrada de tabla de mensajes.
RT_PLUGPLAY
MAKEINTRESOURCE(19)
Plug and Play recurso.
RT_RCDATA
MAKEINTRESOURCE(10)
Recurso definido por la aplicación (datos sin procesar).
RT_STRING
MAKEINTRESOURCE(6)
Entrada de tabla de cadenas. Consulta comentarios a continuación para obtener más información.
RT_VERSION
MAKEINTRESOURCE(16)
Recurso de versión.
RT_VXD
MAKEINTRESOURCE(20)
VXD.

Observaciones

Recursos de tabla de cadenas

Al enumerar recursos de tabla de cadenas (tipo RT_STRING) con funciones como EnumResourceNamesW, el sistema no enumera cada identificador de recurso de cadena individual; en su lugar enumera los bloques de recursos. Debe inspeccionar estos bloques para determinar qué identificadores de recurso de cadena contienen realmente.

Los recursos de cadena se empaquetan en bloques, cada uno de los cuales contiene 16 cadenas con prefijo de longitud que representan 16 identificadores consecutivos (algunos de los cuales pueden no usarse; vea a continuación). Dado un identificador Xde recurso de cadena, se colocará en el número (X \ 16) + 1 de bloque de recursos (donde \ indica la división de enteros). Dentro de ese bloque, el recurso se puede encontrar como la Nprimera entrada, donde N = X % 16.

En la tabla siguiente se muestran algunos identificadores de recursos de cadena de ejemplo y el número de bloque (y desplazamiento) de dónde se ubicarán:

Identificador del recurso Bloquear # Offset
1 (1 \ 16) + 1 = 1 1 % 16 = 1
2 (2 \ 16) + 1 = 1 2 % 16 = 2
5 (5 \ 16) + 1 = 1 5 % 16 = 5
15 (15 \ 16) + 1 = 1 15 % 16 = 15
20 (20 \ 16) + 1 = 2 20 % 16 = 4
32 (32 \ 16) + 1 = 3 32 % 16 = 0
50 (50 \ 16) + 1 = 4 50 % 16 = 2
100 (100 \ 16) + 1 = 7 100 % 16 = 4

Los identificadores de recursos que no se usan (faltan) se indican mediante cadenas de longitud cero. Por lo tanto, en el ejemplo anterior, el bloque #1 tendrá cadenas de longitud cero que representan identificadores 0, 3, 4 y 6 a 14. Ninguna de las cadenas del bloque tiene caracteres NULL terminados, ya que se permite que los recursos de cadena contengan VALORES NUL incrustados. Por lo tanto, el diseño de memoria del bloque 1 tiene este aspecto, suponiendo que el valor de cada cadena sea "Hola mundo" (11 caracteres de longitud) y donde los números entre corchetes angulares representen enteros (no caracteres literales):

<0><11>Hello world<11>Hello world<0><0>
<11>Hello world<0><0><0><0><0><0><0><0>
<0><11>Hello world

El siguiente fragmento de código muestra una función de devolución de llamada de enumeración que enumerará recursos individuales RT_STRING igual que otros tipos (como RT_ICON) en lugar de los bloques:

// Number of entries in the string table.
constexpr UINT STRING_TABLE_SIZE{ 16 };

// Returns the original resource ID from a given block / offset.
inline UINT GetStringResourceIdFromStringTable(LPCWSTR lpName, const unsigned int index)
{
    _ASSERT(index < STRING_TABLE_SIZE);
    return ((reinterpret_cast<UINT>(lpName) - 1) * STRING_TABLE_SIZE) + index;
}

// Helper function that will enumerate string table blocks, looking for resources.
BOOL EnumerateResourceNamesWrapperForStrings(HMODULE hModule, LPWSTR lpName, LONG_PTR lParam, ENUMRESNAMEPROCW lpEnumFunc)
{
    // No need to free or unlock resources in Win32, so OK to throw away intermediates
    auto ptr = (wchar_t*)LockResource(LoadResource(hModule, FindResource(hModule, lpName, RT_STRING)));
    if (ptr)
    {
        for (unsigned int i = 0; i < STRING_TABLE_SIZE; ++i)
        {
            wchar_t size = *ptr;
            if (size > 0)
            {
                auto id = GetStringResourceIdFromStringTable(lpName, i);

                // Invoke the callback for this string resource ID.
                auto callbackResult = lpEnumFunc(hModule, RT_STRING, MAKEINTRESOURCE(id), lParam);
                if (!callbackResult)
                {
                    return callbackResult;
                }
            }
            // Skip to next potential string in the block
            ptr += size + 1;
        }
        return TRUE;
    }

    // Couldn't load the string table entry; something is wrong.
    return FALSE;
}

// Wrapper function for EnumResourceNamesW that will enumerate individual string resources.
BOOL EnumResourceNamesIncludingStringsW(HMODULE hModule, LPCWSTR lpType, ENUMRESNAMEPROCW lpEnumFunc, LONG_PTR lParam)
{
    struct param_wrapper { ENUMRESNAMEPROCW lpEnumFunc; LONG_PTR lParam; } params{ lpEnumFunc, lParam };

    // Use a simple lambda to either call our String helper, or directly call the user's callback
    return EnumResourceNamesW(hModule, lpType, [](auto hModule, auto lpType, auto lpName, auto lParam)
        {
            auto params = reinterpret_cast<param_wrapper*>(lParam);
            if (lpType == RT_STRING)
            {
                return EnumerateResourceNamesWrapperForStrings(hModule, lpName, params->lParam, params->lpEnumFunc);
            }

            return params->lpEnumFunc(hModule, lpType, lpName, params->lParam);
        }, reinterpret_cast<LONG_PTR>(&params));
};

//////////

// Sample callback that just increments a counter.
BOOL CountResources(HMODULE, LPCWSTR, LPWSTR, LONG_PTR lParam)
{
    // Add one to the count...
    (*(reinterpret_cast<UINT*>(lParam)))++;
    return TRUE;
}

// Sample usage:
void CountStringsInExplorer()
{
    auto lib = LoadLibraryExW(LR"(c:\windows\explorer.exe)", nullptr, LOAD_LIBRARY_AS_DATAFILE);
    if (!lib)
    {
        return;
    }

    UINT nStringBlocks{ 0 };
    UINT nStrings{ 0 };

    // Count the number of string blocks using raw Win32 API.
    EnumResourceNamesW(lib, RT_STRING, CountResources, (LONG_PTR)&nStringBlocks);

    // Count the number of actual strings, using the wrapper.
    EnumResourceNamesIncludingStringsW(lib, RT_STRING, CountResources, (LONG_PTR)&nStrings);

    // Outputs something like:
    //
    // Explorer.exe contains 44 strings (in 17 blocks).
    //

    std::wcout << L"Explorer.exe contains " << nStrings << L" strings (in " << nStringBlocks
        << L" blocks)." << std::endl;
}

Requisitos

Requirement Value
Cabecera
Winuser.h