如何使用存储为字符串的MFC资源ID

时间:2014-08-13 04:13:11

标签: string macros mfc resources uint

我正在开发一个MFC应用程序,其中我在.rc文件中定义了菜单。我需要在运行时删除少量菜单项,这些菜单项在xml文件中定义。

菜单ID以字符串形式存储在xml中,如下所示

<exclusionmenu>ID_FILE_NEW</exclusionmenu>
<exclusionmenu>ID_FILE_OPEN</exclusionmenu>

从xml中,菜单ID被检索为字符串

RemoveMenu函数需要UINT(菜单ID),

如何将xml中定义的菜单ID字符串转换为uint菜单ID

注意:这不是直接cstring到uint转换,ID_FILE_NEW是宏,它有int值。

3 个答案:

答案 0 :(得分:2)

资源标识符的符号名称默认在头文件 Resource.h 中定义。在源代码和资源脚本中,预处理器将符号名称替换为它们各自的数值。编译开始时,符号信息已经消失。

要实现使用符号名称进行配置的方案,您必须提取并保留符号名称和资源标识符之间的映射,以便以后在运行时使用,或者在部署之前将映射应用于配置文件。以下是可能的选项列表:

使用关联容器并在应用程序启动时填充它:适当的容器为std::map<std::string, unsigned int>。使用C ++ 11的list initialization功能可以方便地执行此容器的填充:

static std::map<std::string, unsigned int> IdMap = {
    {"ID_FILE_NEW", ID_FILE_NEW},
    {"ID_FILE_OPEN", ID_FILE_OPEN},
    // ...
}

在运行时,您可以使用此容器检索给定其符号常量的资源标识符:

unsigned int GetId(const std::string& name) {
    if (IdMap.find(name) == IdMap.end())
        throw std::runtime_error("Unknown resource identifier.");
    return IdMap[name];
}

这种方法的缺点是你必须保持IdMap和资源同步。无论何时添加,修改或删除资源,都必须更新容器内容以考虑所做的更改。

解析 Resource.h 并存储映射:包含符号标识符名称的头文件具有相当简单的结构。定义符号常量的代码行通常具有以下布局:

\s* '#' \s* 'define' \s+ <name> \s+ <value> <comment>?

提取映射的解析器并不像它看起来那么难实现,应该在构建过程中的适当时间运行。一旦提取了映射,就可以将其存储在任意格式的文件中,例如INI file。此文件既可以与应用程序一起部署,也可以作为资源编译到二进制映像中。在应用程序启动时,将回读内容,并用于构建前一段中所述的映射。与之前的解决方案相比,解析 Resource.h 文件不需要在资源更改时手动更新代码。

解析 Resource.h 并转换配置XML文件:与以前的解决方案一样,此选项还需要解析 Resource.h 文件。使用此信息,然后可以转换配置XML文件,在部署之前用符号名称替换它们的数字对应物。这也需要额外的工作。但是,一旦完成,该过程可以自动化,并验证结果以保持一致性。在运行时,您可以简单地读取XML并使数字标识符随时可用。

答案 1 :(得分:1)

您的方案可以使用的唯一方法是使用您的应用程序分发Resoutce.h,并且您有逻辑在启动时将Resource.h解析为包含ID_ *名称及其值的表。

答案 2 :(得分:0)

你不能,字符串形式在编译时'丢失',它是一个预处理器令牌。您可以存储菜单项的字符串变体:在代码中的某处,使用std :: map并用值填充它:menu_ids [“ID_FILE_NEW”] = ID_FILE_NEW;然后调用RemoveMenu(menu_ids [string_from_xml]);