从资源中加载字符串的C++ Win32

8
好的,最近我决定把应用程序中的每个字符串都放入STRINGTABLE中,以便轻松地翻译成不同的语言。我知道如何使用LoadString() api,但这意味着我需要为要加载的每个字符串创建一个不同的变量,如果我的应用程序有100个字符串,那就需要很多变量。这是最好的方法吗?还是应该创建一个全局变量作为缓冲区来根据需要加载字符串?此外,由于不知道我的字符串有多大,所以是否应该创建足以容纳任何可能存在的字符串的足够大的缓冲区,或者是否有更好的方法做到这一点?
另外,按需加载字符串对性能有影响吗?有没有办法预加载它们?
更新:好的,我尝试创建大小为256个字节的缓冲区,并根据需要将字符串加载到其中,但遇到了一些问题...
以下是显示错误消息的代码,错误是“分配内存时出错!”
LoadString(g_hInst, IDS_ERROR_MEMORY, szBuffer, sizeof(szBuffer)/sizeof(TCHAR)); MessageBox(NULL, szBuffer, TEXT("Error"), MB_OK | MB_ICONERROR); ExitProcess(1);
而我将我的缓冲区作为全局变量: TCHAR szBuffer[256];
这可以工作,但是,我想在字符串表中也存储“Error”文本,并在显示错误时加载该文本,问题是这将要求我有两个全局变量来加载字符串,而有些地方需要一次加载甚至更多。有没有比拥有多个全局变量更好的解决方案?

使用支持本地化的GUI框架会更加容易。 - David Heffernan
1个回答

9
如果您希望预加载它们,那么可以这样做。您只需要创建一个字符串指针数组,并将每个字符串加载到该数组中。或者您可以使用哈希表或类似的东西。

是否会影响性能?这取决于情况。如果您要在用户界面中显示这些字符串作为提示信息,我认为按需加载每个字符串不会对性能造成问题。操作系统会进行一些智能缓存,因此您不必为每个需要显示的字符串访问磁盘。另一方面,如果您要在紧密循环中处理这些字符串,则最好将它们预加载到内存中,这样您就不必一直调用LoadString

至于缓冲区,我总是分配一个与我期望在资源文件中拥有的最大字符串相同大小的缓冲区。考虑到用户界面字符串通常非常小,256字节的缓冲区已经足够了。任何比那更大的东西,我要么在启动时预先加载到内存中以便保留它,要么编写一个单独的方法,在加载时分配字符串而不是保留缓冲区。

其他信息:

除了为您的字符串定义全局变量之外,还可以编写一个函数来加载资源字符串,复制它,并返回该副本。也就是说:

char * LoadStringFromResource(uint id)
{
    // szBuffer is a globally pre-defined buffer of some maximum length
    LoadString(ghInst, id, szBuffer, bufferSize);
    // yes, I know that strdup has problems. But you get the idea.
    return strdup(szBuffer);
}

你的代码将变成:

你的代码,然后变成:

char* errMem = LoadStringFromResource(IDS_ERROR_MEMORY);
char* errText = LoadStringFromResource(IDS_ERROR_TEXT);
MessageBox(NULL, errMem, errText, MB_OK | MB_ICONERROR);
free(errMem);
free(errText);

上面是C代码,但是你可以很容易地转换为C++。特别是,你可能想要修改包装函数,使其返回一个C++字符串——当它超出作用域时将自动释放(使用智能指针或者现代等效物)。


strdup()不是ISO C标准的一部分,它更多地属于Posix。MinGW接受在GNU C方言中编译。 - Salvador
2
哇,因为我在示例中使用了 strdup 而被踩了?太苛刻了。我甚至在注释中解释了我的用法,以免受到指责。噢,好吧,不能讨好每个人。 - Jim Mischel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接