資源類型

以下是預先定義的資源類型。

Constant/value Description
RT_ACCELERATOR
MAKEINTRESOURCE(9)
加速台。
RT_ANICURSOR
MAKEINTRESOURCE(21)
動畫游標。
RT_ANIICON
MAKEINTRESOURCE(22)
動畫圖示。
RT_BITMAP
MAKEINTRESOURCE(2)
點陣圖資源。
RT_CURSOR
MAKEINTRESOURCE(1)
依賴硬體的游標資源。
RT_DIALOG
MAKEINTRESOURCE(5)
對話框。
RT_DLGINCLUDE
MAKEINTRESOURCE(17)
允許資源編輯工具將字串與 .rc 檔案關聯。 通常,字串是提供符號名稱的標頭檔名稱。 資源編譯器會解析字串,但其他時候會忽略該值。 例如,
1 DLGINCLUDE "MyFile.h"
RT_FONT
MAKEINTRESOURCE(8)
字體資源。
RT_FONTDIR
MAKEINTRESOURCE(7)
字型目錄資源。
RT_GROUP_CURSOR
MAKEINTRESOURCE((ULONG_PTR)(RT_CURSOR) + 11)
硬體無關的游標資源。
RT_GROUP_ICON
MAKEINTRESOURCE((ULONG_PTR)(RT_ICON) + 11)
硬體無關的圖示資源。
RT_HTML
MAKEINTRESOURCE(23)
HTML 資源。
RT_ICON
MAKEINTRESOURCE(3)
硬體相關的圖示資源。
RT_MANIFEST
MAKEINTRESOURCE(24)
並排組裝清單。
RT_MENU
MAKEINTRESOURCE(4)
選單資源。
RT_MESSAGETABLE
MAKEINTRESOURCE(11)
訊息表條目。
RT_PLUGPLAY
MAKEINTRESOURCE(19)
隨插即用 資源。
RT_RCDATA
MAKEINTRESOURCE(10)
應用程式定義資源(原始資料)。
RT_STRING
MAKEINTRESOURCE(6)
字串表條目。 更多資訊請參閱下方 備註 。
RT_VERSION
MAKEINTRESOURCE(16)
版本資源。
RT_VXD
MAKEINTRESOURCE(20)
VXD。

備註

字串表資源

當以 EnumResourceNamesW 等函式枚舉字串表資源(類型 RT_STRING)時,系統不會枚舉每個字串資源 ID;它會列舉資源區塊。 你必須檢查這些區塊,以確定它們實際包含哪些字串資源 ID。

字串資源被打包成區塊,每個區塊包含 16 個以長度為前綴的字串,代表 16 個連續的 ID(其中部分可能未被使用;詳見下文)。 給定一個字串資源 ID X,會將其置於資源區塊編號 (X \ 16) + 1 中(其中 \ 表示整數除法)。 在該區塊中,資源可作為第 個項目找到 N,其中 N = X % 16。

下表顯示了一些字串資源 ID 範例及其區塊號(及偏移量)位置:

資源識別碼 區塊# 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

任何未使用(缺失)的資源 ID 以零長度字串表示。 在上述範例中,區塊 #1 的字串長度為零,分別代表 ID 0、3、4 和 6 - 14。 該區塊中沒有任何字串包含終止的 NULL 字元,因為允許字串資源包含嵌入的 NULL。 因此,區塊 #1 的記憶體配置如下,假設每個字串的值為「Hello world」(11 個字元長),且括號內的數字代表整數(而非字元):

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

以下程式碼片段展示了一個列舉回調函式,會像其他類型(如 RT_ICON)一樣,列舉個別RT_STRING資源,而非區塊:

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

需求 價值
Header
Winuser.h