使用WinAPI在运行时向资源添加字符串

时间:2012-11-15 09:26:44

标签: c++ winapi

是否可以在运行时向STRINGTABLE资源添加字符串? 我有一个连接到主机应用程序的插件,它希望使用LoadString方法传递字符串。在我看来,我只能在运行时准备数据(通常在启动期间一次)。我已经在运行中准备了DLGTEMPLATE结构,有类似的方法来处理STRINGTABLE吗? 还有其他解决办法吗?

谢谢,

1 个答案:

答案 0 :(得分:0)

正如enhzflep建议的那样,我更新了一个单独的PE文件。获得正确的字符串更新需要一些尝试和错误,所以我在这里发布我的解决方案。

一个注意事项:我正在顺序写字符串。使用16个字符串的块更新资源非常重要,因此使用预定义ID编写字符串将涉及编写一些空字符串。

const int RESOURCE_STRING_START = 1 << 14; /// custom start ID value
std::vector<std::wstring> m_resource_strings;

/// add strings ///

HANDLE lib_handle = BeginUpdateResource( library_name, TRUE);

size_t string_section_size = 0;
for (int i = 0; i < m_resource_strings.size(); i++)
    string_section_size += m_resource_strings[i].length() * sizeof(WCHAR);

HGLOBAL heap = GlobalAlloc(GMEM_ZEROINIT, string_section_size); 
if (!heap) {
    return false;
}
/// Create temporary memory pool ///
WORD* heap_start = (WORD*)GlobalLock(heap);
if (!heap_start) {
    return false;
}
WORD* pos = NULL;

for (int i = 0; i < m_resource_strings.size(); i+=16)
{
    pos = heap_start;
    const int section = 1 + ((RESOURCE_STRING_START + i) >> 4);
    for (int j = 0; j < 16; j++)
    {
        if ( i+j < m_resource_strings.size() ) {
            std::wstring& str = m_resource_strings[j+i];
            *pos++ = str.length(); /// Write string length
            memcpy( pos, str.data(), str.length() * sizeof(WCHAR) ); /// Copy string
            pos += str.length();
        }
        else *pos++ = 0;
    }
    if (!UpdateResource(lib_handle, RT_STRING, (LPTSTR)(ULONG_PTR)section, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), heap_start, DWORD(pos) - DWORD(heap_start) ))
    {
        GlobalFree(heap);
        return false;
    }
}
GlobalFree(heap);

if (!EndUpdateResource( lib_handle, FALSE )) {
    return false;
}