我在vs资源.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:值),...],...]std::map<long /*languageId*/, std::map<long /*resource id (1000, 7777, 1001)*/, std::string /*value*/>>
我不知道.rc
文件中有多少资源,我也不知道资源ID(我希望有某种方法可以从文件中获取所有ID,但到目前为止我还没有找到这样做的方法)
我努力
通过回调循环访问资源。
#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的资源的句柄,但从这里我不清楚如何获取
1.给定资源句柄的可用资源id列表
1.实际获取资源的值
在锁定资源后,wchar_t *data
中似乎有一些东西,但它似乎没有以任何方式为STRINGTABLE
进行结构化,也许它可以用于二进制资源,但STRINGTABLE
似乎不可解析
我还尝试了什么
只是调用LoadString,但是
1.我不能指定语言(也不能乱用系统或应用程序区域设置)
1.我不知道如何获取可用资源ID
编辑:增加了更多的调查对通过LockResource获取数据
3条答案
按热度按时间6vl6ewon1#
STRING TABLE资源在这里有一些记录:https://devblogs.microsoft.com/oldnewthing/20040130-00/?p=40813
(PS:这里有一个链接到上述知识库文章Q196774:https://www.betaarchive.com/wiki/index.php/Microsoft_KB_Archive/196774)
在 *.rc文件中列出的字符串以十六个一组的形式组合在一起。因此,第一束包含字符串0到15,第二束包含字符串16到31,依此类推。通常,束N包含字符串(N-1)*16到(N-1)*16+15。
每个包中的字符串都存储为计数的UNICODE字符串,而不是以null结尾的字符串。如果编号中存在间隙,则使用空字符串。例如,如果你的字符串表只有字符串16和31,那么就会有一个bundle(2号),它由字符串16、14个null字符串和字符串31组成。
下面是一些从给定文件中转储所有字符串资源的示例代码:
v440hwme2#
Windows应用程序中的多语言资源加载由
1.使用SetThreadLocale API设置区域设置。
1.调用LoadResource(或者更具体的API,如LoadMenu、LoadString)
要加载资源,应该知道其ID。如果要枚举所有资源,请使用EnumResource* API。
apeeds0o3#
下面的链接由@SimonMourier提供我写的代码读取所有资源。
EnumResourceLanguagesCallback
可能会被多次调用,即使是对于一个资源文件,它似乎每次调用都要解析大约33-34个资源,但它可能会因为某种原因注册一些资源两次。此代码仍然无法获取资源ID。