Я перевел строки для нескольких языков в зависимости от ресурса .rc
файлы, хранящиеся в STRINGTABLE
//english.rc
#pragma code_page(65001)
#define APSTUDIO_READONLY_SYMBOLS
#include "afxres.h"
#undef APSTUDIO_READONLY_SYMBOLS
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
STRINGTABLE
BEGIN
1000 "SOME TEXT"
7777 "SOME TEXT"
END
#endif
//danish.rc
#pragma code_page(65001)
#define APSTUDIO_READONLY_SYMBOLS
#include "afxres.h"
#undef APSTUDIO_READONLY_SYMBOLS
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_DANISH, SUBLANG_NEUTRAL
STRINGTABLE
BEGIN
1001 "SOME TEXT IN DANISH"
7777 "SOME TEXT IN DANISH"
END
#endif
Я хочу загрузить эти ресурсы на карту [languageId: [(resourceId: value) , ...], ...]
std::map<long /*languageId*/, std::map<long /*resource id (1000, 7777, 1001)*/, std::string /*value*/>>
Я не знаю, сколько ресурсов содержится в файлах .rc
, я также не знаю идентификаторов ресурсов (ожидаю есть какой-то способ получить все идентификаторы из файла, но я до сих пор не нашел способ сделать это)
Что я пытался
Итерация по ресурсам через обратный звонок.
#include <iostream>
#include <windows.h>
#include <map>
BOOL EnumResourceLanguagesCallback(HMODULE applicationModule, LPCTSTR resourceType, LPCTSTR resourceName, WORD languageId, std::map<long /*languageId*/, std::map<long /*resource id (e.g. 1000, 7777, 1001)*/, std::string /*resource value*/>> * pResources)
{
HRSRC hResInfo = FindResourceEx(applicationModule, resourceType, resourceName, languageId);
HGLOBAL hData = LoadResource(0, hResInfo);
std::wstring values;
values.assign((wchar_t*)LockResource(hData), SizeofResource(applicationModule, hResInfo));
/* values string is either empty or contains garbage or sometimes partial string with some of the resources in the rc file - depends on the amount of resources in rc file*/
return TRUE;
}
BOOL EnumResourceNamesCallback(HMODULE applicationModule, LPCTSTR resourceType, LPTSTR resourceName, std::map<long /*languageId*/, std::map<long /*resource id (e.g. 1000, 7777, 1001)*/, std::string /*resource value*/>> *pResources)
{
return EnumResourceLanguages(applicationModule, resourceType, resourceName, (ENUMRESLANGPROC)EnumResourceLanguagesCallback, reinterpret_cast<LONG_PTR>(pResources));
}
int main()
{
std::map<long /*languageId*/, std::map<long /*resource id (e.g. 1000, 7777, 1001)*/, std::string /*resource value*/>> resources;
EnumResourceNames(::GetModuleHandleA(nullptr), RT_STRING, (ENUMRESNAMEPROC)EnumResourceNamesCallback, reinterpret_cast<LONG_PTR>(&resources));
}
Это дало мне все дескрипторы ресурсов с возможностью вызова LoadResource & LockResource, но здесь мне неясно, как получить
- Список доступных идентификаторов ресурсов для данный дескриптор ресурса
- Фактически получить значение ресурса
Кажется, что-то есть в wchar_t *data
после блокировки ресурса, но, похоже, он не структурирован в в любом случае для STRINGTABLE
, может быть, это будет работать для двоичного ресурса, но формат STRINGTABLE
не кажется доступным для анализа
Что еще я пробовал
Просто вызывая LoadString, но для этого
- я не могу указать язык (и не могу связываться с языком системы или приложения)
- Я не знаю, как получить доступные идентификаторы ресурсов
РЕДАКТИРОВАТЬ: Добавлено больше исследований для получения данных через LockResource