Tipi di risorse

Di seguito sono riportati i tipi di risorse predefiniti.

Constant/value Description
RT_ACCELERATOR
MAKEINTRESOURCE(9)
Tabella di tasti di scelta rapida.
RT_ANICURSOR
MAKEINTRESOURCE(21)
Cursore animato.
RT_ANIICON
MAKEINTRESOURCE(22)
Icona animata.
RT_BITMAP
MAKEINTRESOURCE(2)
Risorsa bitmap.
RT_CURSOR
MAKEINTRESOURCE(1)
Risorsa cursore dipendente dall'hardware.
RT_DIALOG
MAKEINTRESOURCE(5)
Finestra di dialogo.
RT_DLGINCLUDE
MAKEINTRESOURCE(17)
Consente a uno strumento di modifica delle risorse di associare una stringa a un file RC. In genere, la stringa è il nome del file di intestazione che fornisce nomi simbolici. Il compilatore di risorse analizza la stringa, ma in caso contrario ignora il valore. Ad esempio,
1 DLGINCLUDE "MyFile.h"
RT_FONT
MAKEINTRESOURCE(8)
Risorsa tipo di carattere.
RT_FONTDIR
MAKEINTRESOURCE(7)
Risorsa directory font.
RT_GROUP_CURSOR
MAKEINTRESOURCE((ULONG_PTR)(RT_CURSOR) + 11)
Risorsa cursore indipendente dall'hardware.
RT_GROUP_ICON
MAKEINTRESOURCE((ULONG_PTR)(RT_ICON) + 11)
Risorsa icona indipendente dall'hardware.
RT_HTML
MAKEINTRESOURCE(23)
Risorsa HTML.
RT_ICON
MAKEINTRESOURCE(3)
Risorsa icona dipendente dall'hardware.
RT_MANIFEST
MAKEINTRESOURCE(24)
Manifesto dell'assembly affiancato.
RT_MENU
MAKEINTRESOURCE(4)
Risorsa del menu.
RT_MESSAGETABLE
MAKEINTRESOURCE(11)
Voce message-table.
RT_PLUGPLAY
MAKEINTRESOURCE(19)
Plug and Play risorsa.
RT_RCDATA
MAKEINTRESOURCE(10)
Risorsa definita dall'applicazione (dati non elaborati).
RT_STRING
MAKEINTRESOURCE(6)
Voce di tabella stringa. Per altre info, vedi la sezione Osservazioni di seguito.
RT_VERSION
MAKEINTRESOURCE(16)
Risorsa versione.
RT_VXD
MAKEINTRESOURCE(20)
VXD.

Osservazioni:

Risorse tabella stringhe

Durante l'enumerazione delle risorse di tabella stringhe (tipo RT_STRING) con funzioni come EnumResourceNamesW, il sistema non enumera ogni SINGOLO ID risorsa stringa; enumera invece blocchi di risorse. È necessario esaminare questi blocchi per determinare quali ID risorsa stringa contengono effettivamente.

Le risorse stringa vengono inserite in blocchi, ognuna delle quali contiene 16 stringhe con prefisso di lunghezza che rappresentano 16 ID consecutivi (alcuni dei quali potrebbero non essere usati; vedere di seguito). Dato un ID Xrisorsa stringa, verrà inserito nel numero (X \ 16) + 1 di blocco della risorsa (dove \ indica la divisione integer). All'interno di tale blocco, la risorsa può essere trovata come Nla prima voce, dove N = X % 16.

La tabella seguente mostra alcuni ID risorsa stringa di esempio e il numero di blocco (e offset) di dove si trovano:

ID risorsa Blocca # 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

Gli ID risorsa inutilizzati (mancanti) sono contrassegnati da stringhe di lunghezza zero. Nell'esempio precedente, quindi, il blocco 1 avrà stringhe di lunghezza zero che rappresentano GLI ID 0, 3, 4 e 6 - 14. Nessuna delle stringhe nel blocco ha caratteri NULL di terminazione, poiché è consentito alle risorse stringa di contenere valori NULL incorporati. Di conseguenza, il layout di memoria del blocco #1 è simile al seguente, presupponendo che il valore di ogni stringa sia "Hello world" (lunghezza di 11 caratteri) e in cui i numeri tra parentesi angolari rappresentano numeri interi (non caratteri letterali):

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

Il frammento di codice seguente mostra una funzione di callback di enumerazione che enumera le singole risorse RT_STRING come gli altri tipi (ad esempio RT_ICON) anziché i blocchi:

// 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;
}

Requirements

Requisito Value
Intestazione
Winuser.h