如何在MFC中为不同的构建目标使用不同的资源文件

时间:2013-03-27 04:48:24

标签: visual-studio visual-c++ build mfc target

我有一些目标特定的资源。就像目标客户端的不同对话框和目标 admin 的不同对话框一样。还有一些特定于每个目标的字符串。我不希望管理员应用程序特有的资源和代码出现在客户端构建中。

假设我可以有3个资源文件,管理员客户端常见,并以某种方式告诉构建引擎使用 admin < / strong>和常见 res用于管理员构建,并使用客户端常用资源进行客户端构建。

我怎样才能做到这一点?

如何拥有多个资源文件并使用资源文件进行特定的目标构建。?

4 个答案:

答案 0 :(得分:8)

好的,这是我完全回答你的问题,如果只是获得赏金会很有趣(他们不会经常在MFC标记的问题中发生:))。请说明您认为哪些问题没有得到解决,如果有的话。这与VS 2008一样,对其他版本的更改应该是最小的。

  • 首先为每个不同的构建目标添加资源文件,例如: “admin.rc”,“common.rc”等。在解决方案浏览器中,右键单击项目“添加 - >新项目 - >资源文件”。

  • 在解决方案浏览器中右键单击新添加的资源文件,选择“属性”,然后在“常规”下将“从构建中排除”设置为“是”。

  • 在资源视图中,您现在可以将所需资源添加到相应的资源文件中。

  • 接下来,在资源视图中,右键单击“主”资源文件()并选择“资源包含”。

  • 在下方框中,在任何内容的末尾添加

#ifdef ADMIN
#include "admin.rc"
#endif

当然,您可以自行选择预处理器中使用的符号,文件名需要与之前创建资源文件时选择的内容相匹配。

  • 然后,在“管理”项目配置中(我假设您为每个目标使用不同的配置?),在解决方案资源管理器中,右键单击您的项目并导航到“资源 - &gt;一般”。在“预处理器定义”下,添加“ADMIN”(或您在上一步中选择的任何内容)。

  • 构建您的解决方案。您可以使用http://www.wilsonc.demon.co.uk/d10resourceeditor.htmhttp://melander.dk/reseditor/等内容验证二进制文件中包含的资源。

请注意,显然您必须考虑各种构建中不可用的资源;所以你必须确保例如没有显示将在其构造函数中使用对话框IDD的对话框。您也可以通过预处理器执行此操作;只需在相应的配置中将相同的标志添加到C ++预处理器中。

另一个问题是每个.rc文件都有一个resource.h,它们每个都会使用自己的编号。您可以通过仔细的命名和编号来完成这项工作,但我会为每个分配不同的范围,以便在编译时捕获尽可能多的问题。要执行此操作,请打开“resource1.h”或您调用的任何内容,并将_APS_NEXT__VALUE定义更改为更高的数字。

或者,您可以将所有资源定义粘贴到一个resource.h中,并编辑所有.rc文件以包含该一个resource.h。只需右键单击解决方案资源管理器中的rc文件,然后选择“打开方式”并单击“源代码编辑器”。如果你要沿着“复杂的资源构建”路线走,你必须熟悉rc文件的格式(至少对于基础知识)。这并不难,只要确保你能够了解链接器,资源编译器,.rc文件,.cpp文件和resource.h文件是如何相互关联的。此外,MFC特定的预处理器值一开始看起来令人生畏,但它们大部分都是不言自明的,无论如何你都可以忽略它们。

Petzold对资源文件及其格式有一个简洁但充分的解释,你可能想把它从壁橱中挖出来,并在你掌握一切东西的时候把它放在手边。

答案 1 :(得分:5)

您可以在.rc文件中使用#ifdef。但是这会搞砸资源编辑器。解决这个问题的“标准”方法是为每个目标分别使用.rc文件,然后在一个脚本中#include它们中的#ifdef,例如。

#ifdef CLIENT_1
#include "client_1.rc"
#endif
#ifdef CLIENT_2
#include "client_2.rc"
#endif

这样资源编辑器只需要解析“完整”的rc文件。尽管如此,这样的工作很痛苦,因为编辑很容易混淆。曾几何时,我还尝试为每个“目标”设置一个单独的项目,然后在我的“资源包含”部分中使用相对路径#include它们。我不记得为什么我最后没有使用这种方法。使用预处理器可以使这个工作,但它总是感觉有点笨拙。也许VS的最新版本可以更好地处理它。

答案 2 :(得分:4)

根据给定的描述,我认为不需要不同的.RC文件。您可以拥有一个包含两个(或多个目标)字符串的字符串表。在启动时,您将拥有指向其中任何一个的UINT变量。例如:

UINT nUserConfirmationId;
UINT nAcessDeiniedMsgId;

if(target1)
{
   nUserConfirmationId = IDD_ENG_STRING_ID_FOR_CONFIRM;
   ..
}
else
{
   nUserConfirmationId = IDD_FRE_STRING_ID_FOR_CONFIRM;
   ...
}

然后使用nUserConfirmationId等变量。类似的方式,您可以拥有对话框资源(我不明白为什么您需要不同的对话框,只应替换字符串)。 是的,当您添加资源时,它会出现维护问题。

或者,您可以拥有仅限资源的DLL,它将包含目标特定资源。

答案 3 :(得分:0)

如果您只有一些特定于配置的资源,您可能会发现在配置之间共享 .rc 更容易且更易于维护,但让它们使用不同的资源子集。 VS(2017年至少)也支持它:为个人资源添加条件

解决方案资源管理器中,双击 .rc 以打开资源视图。在资源树中,右键单击您希望与配置相关的对话框,图标等,然后打开属性

在属性窗口中,您应该看到条件

现在,您应该已经拥有专门为您的客户端,服务器和管理员构建定义的预处理器符号。 (如果您不这样做,请立即执行此操作!属性页 - &gt; C / C ++ - &gt;预处理程序 - &gt;预处理程序定义。)

只需将此符号添加到条件即可。这样可以在 .rc 文件的代码块周围添加#ifdef ... #endif,但是以VS友好的方式 - 它没有&#39打破编辑。

注意:但是,我注意到这个过程似乎不适用于字符串表。无法判断它是UI错误还是根本不受支持。