TN035:使用多个资源文件和标头文件具有Visual C++的

说明说明

以下技术声明,则它在联机文档,首先包括了不更新。因此,某些过程和主题可能已过时或不正确。有关最新信息,建议您搜索议题在联机文档的索引。

此说明描述了 Visual C++ 资源编辑器如何支持多个资源文件并在多个项目间共享在单个项目或共享的头文件,并且支持的可利用。此说明回答以下问题:

  • 您可能希望拆分项目划分为多个资源文件和标头文件,因此,您呢?

  • 如何共享一个公共标头。在两 .RC 文件之间的 H 文件?

  • 您如何将项目资源划分为多个 .RC 文件?

  • 如何执行您 (和工具) 管理在 .RC, .CPP 之间的生成依赖项,和。H 文件?

您应该知道,如果您将一个附加资源文件添加到项目中,类向导将无法识别在添加的文件的资源。

构造此说明回答以下问题如下所示:

  • Overview of How Visual C++ Manages Resource Files and Header Files 概述设置的资源如何在 Visual C++ 在同一项目包括命令可以使用多个资源文件和标头文件。

  • Analysis of AppWizard-created .RC and .H Files 查看一 AppWizard 创建的应用程序使用的多个资源文件和头文件。这些文件作为一个好的设计用作您可能希望添加到项目中的其他资源文件和标头文件。

  • Including Additional Header Files 描述您可能希望包括多个头文件的位置,并提供详细说明如何执行此操作。

  • Sharing a Header File Between Two .RC Files 在同一项目演示如何共享在多个 .RC 文件之间的头文件在不同的项目,或者。

  • Using Multiple Resource Files in the Same Project 描述您可能希望将您的项目多个 .RC 文件的位置,并提供详细说明如何执行此操作。

  • Enforcement of Non-Editable Visual C++ Files 描述如何确定 Visual C++ 不能编辑和不会无意重新设置自定义资源。

  • Managing Symbols Shared by Multiple Visual C++-Edited .RC Files 描述如何共享在多个 .RC 文件中的符号,以及如何避免分配重复 ID 数值。

  • Managing Dependencies Between .RC, .CPP, and .H Files 描述 Visual C++ 如何避免依赖资源符号文件不必要的重新编译的 .CPP 文件。

  • How Visual C++ Manages Set Includes Information 提供有关 Visual C++ 如何的技术详细信息记录是 #include'd 由 .RC 文件的多个 (嵌套) .RC 文件和多个头文件。

概述 Visual C++ 如何管理资源文件和标头文件

Visual C++ 管理单个 .RC 资源文件和一个对应。H 作为紧密耦合的头文件对文件。在编辑并保存在 .RC 文件中的资源,则取消编辑并保存在相应的符号。H 文件。虽然可以一次打开和编辑多个 .RC 文件 (使用 Visual C++ 的 MDI 用户界面) 任何给定 .RC 文件可以确切地取消编辑一个对应的头文件。

符号头文件

默认情况下, Visual C++ 始终命名相应头文件 RESOURCE.H,无论资源文件 (即, MYAPP.RC) 的名称。使用从 查看 菜单的 资源包括 命令在 Visual C++ 中,可以通过更新在 Set Includes 对话框的符号头文件更改此头文件的名称。

只读符号指令

虽然 Visual C++ 仅编辑任何特定 .RC 文件的头文件, Visual C++ 支持对附加的只读的头文件中定义的符号。使用从 查看 菜单的 资源包括 命令在 Visual C++ 中,可以指定任意数量的附加的只读头文件为只读符号指令。该 “只读”限制意味着,当您将在 .RC 文件中的新资源,可以在只读头文件中使用定义的符号;,但是,如果您删除该资源,符号在只读的头文件仍保持定义。您无法将该数值赋给只读符号。

编译时指令

Visual C++ 还支持嵌套资源文件,且 .RC 文件位于另一个应用程序内的 #include'd。使用 Visual C++ 时,编辑特定 .RC 文件,在 #include'd 文件的任何资源不可见。,但,当您生成 .RC 文件时, #include'd 文件进行编译。使用从 查看 菜单的 资源包括 命令在 Visual C++ 中,可以指定任意数量的 #include'd .RC 文件作为编译时指令。

说明发生什么情况,则读取到 Visual C++ 没有指定为编译时指令的 .RC 文件中包括的其他 .RC 文件。此缺陷可能出现,当您对 Visual C++ 将手动之前保持与文本编辑器的 .RC 文件中。在 Visual C++ 读取 #include'd .RC 文件时,它包含 #include'd 资源到父 .RC 文件。当您保存父 .RC 文件, #include 语句将 #include'd 资源,但实际上,替换。如果不希望此池发生,应从父 .RC 文件中移除 #include 语句 读取之前到 Visual C++ 中;使用 Visual C++,然后,添加 #include 语句和编译时指令相同。

Visual C++ 在上面设置中的三包括信息的 .RC 文件保存 (符号头文件、只读符号指令和编译时指令) 在 #include 指令 在 TEXTINCLUDE 资源。TEXTINCLUDE 资源,则通常不需要处理的实现详细信息,在 Visual C++ 如何管理设置包括信息解释。

为 AppWizard 创建的 .RC 的分析和。H 文件

检查 AppWizard 生成的应用程序代码提供深入了解 Visual C++ 如何管理多个资源文件和标头文件。在下选中的代码摘要是从 AppWizard 生成的 MYAPP 应用程序使用默认选项。

一 AppWizard 创建的应用程序如总结下图使用多个资源文件和多个头文件,例如:

   RESOURCE.H     AFXRES.H                    
          \       /                              
           \     /                                
          MYAPP.RC                               
              |                                
              |                              
        RES\MYAPP.RC2  
        AFXRES.RC                   
        AFXPRINT.RC                 

可以查看这些设置多个文件的关系使用 Visual C++ 文档/包括命令。

  • MYAPP.RC
    使用 Visual C++ 时,可以编辑应用程序资源文件。

RESOURCE.H 是特定于应用程序的头文件。它始终按 AppWizard 名为的 RESOURCE.H,符合 Visual C++ 的默认命名头文件。此头文件中的 #include 是在资源文件 (MYAPP.RC) 的第一个语句:

//Microsoft Visual C++ generated resource script
//
#include "resource.h"
  • RES \ MYAPP.RC2
    在最终生成 .exe 文件包含不会由 Visual C++ 编辑的资源,但包括。默认情况下 AppWizard 不创建此类资源,,因为 Visual C++ 能编辑所有标准资源,包括版本资源 (在此版本中的新功能)。但是,如果您希望将自定义格式化的资源添加到此文件,空文件由 AppWizard 生成的。

如果您使用自定义格式化的资源,则使用 Visual C++ 文本编辑器,您可以将它们添加到 RES \ MYAPP.RC2 和编辑它们。

AFXRES.RC 和 AFXPRINT.RC 包含框架的某些功能所需的标准资源。如 RES \ MYAPP.RC2,这两种结构提供了资源文件是 #include'd 在 MYAPP.RC 末尾,并且,它们在测试设置中编译时指令指定包含对话框。因此,不直接查看也不能编辑这些结构资源,在编辑在 Visual C++ 中 MYAPP.RC,但是,它们会编译到应用程序的二进制 .RES 文件和最终 .exe 文件。有关标准 framework 资源的更多信息,包括修改的这些方法,请参见 技术说明 23

AFXRES.H 定义标准符号,如 ID_FILE_NEW,使用该结构和专门用于 AFXRES.RC。还 AFXRES.H #include 的 WINRES.H,包含 WINDOWS.H 的子集由 Visual C++ 需要生成了 .RC 文件以及 AFXRES.RC。在 AFXRES.H 定义的符号可用,当您编辑应用程序资源文件 (MYAPP.RC)。例如, ID_FILE_NEW 为文件的菜单项使用在 MYAPP.RC 菜单资源。您不能更改或删除这些框架定义的符号。

包括附加的头文件

AppWizard 创建的应用程序只包含两个头文件:RESOURCE.H 和 AFXRES.H。仅 RESOURCE.H 特定于应用程序。您可能需要在以下情况下包括附加的只读的头文件:

外部源提供头文件,或者您希望共享头文件在多个项目或同一项目中的多个部分。

头文件格式有和注释您不希望 Visual C++ 更改或筛选,以便保存文件时。例如,您可能希望保留请使用符号算术的 #define 的:

#define RED 0
#define BLUE 1
#define GREEN 2
#define ID_COLOR_BUTTON 1001
#define ID_RED_BUTTON (ID_COLOR_BUTTON + RED)
#define ID_BLUE_BUTTON (ID_COLOR_BUTTON + BLUE)
#define ID_GREEN_BUTTON (ID_COLOR_BUTTON + GREEN)

您可以包括其他的只读头文件使用 资源包括 命令指定 #include 语句作为第二个只读符号指令,如下所示:

#include "afxres.h"
#include "second.h"

新文件关系关系图现在如下所示:

                   AFXRES.H       
    RESOURCE.H     SECOND.H                    
          \       /                              
           \     /                                
          MYAPP.RC   
              |                                
              |                              
        RES\MYAPP.RC2  
        AFXRES.RC                   
        AFXPRINT.RC                 

共享在两个 .RC 文件之间的头文件

您可能需要共享在不同的项目中的两个 .RC 文件,也可以在同一个项目之间的头文件。为此,请将应用于中描述的只读指令技术上面两 .RC 文件。在两 .RC 文件是不同的应用程序的情况 (不同的项目),结果将下图阐释:

     RESOURCE.H   AFXRES.H   RESOURCE.H  
    (for MYAPP1)  SECOND.H   (for MYAPP2)             
          \       /     \       /           
           \     /       \     /             
          MYAPP1.RC      MYAPP2.RC                 
           /    \        /     \                   
          /      \      /       \            
RES\MYAPP1.RC2  AFXRES.RC     RES\MYAPP2.RC2              
                AFXPRINT.RC                 

第二个头文件由位于同一应用程序的情况 (项目) 的两个 .RC 文件共享如下所述。

使用在同一项目的多个资源文件

Visual C++ 和资源编译器将 .RC 文件的 #include 在另一个中的支持在同一项目的多个 .RC 文件。多个嵌套允许的。有多种原因拆分项目的资源划分为多个 .RC 文件:

  • ,如果资源拆分为多个 .RC 文件,管理在多个项目团队成员中的大量资源更为方便。如果对检查文件并检查使用受源代码管理包在更改,资源拆分为多个 .RC 文件中将为您提供对托管更改的更好地控制对资源。

  • 如果要使用预处理器指令,如 #ifdef, #endif,并且, #define,资源的部分,必须确定它们在将由资源编译器生成的只读资源。

  • 组件 .RC 文件在 Visual C++ 比复合 .RC 文件快地将加载和保存。

  • 如果您希望维护与一个文本编辑器的资源提供一种可读的形式,可以在 .RC 文件应保留其分开的 Visual C++ 版本。

  • 如果在二进制文件需要保留一个用户定义的资源或由另一个专用编辑数据可解释的文本形式,则在单独 .RC 文件应将它保存,因此 Visual C++ 不会更改窗体中十六进制数据。在 MFC 高级概念的示例 SPEAKN 的 .WAV (声音) 文件资源是一个很好的示例。

还可以在编译时指令的 SECOND.RC 在测试设置中包括对话框中的 #include:

#include "res\myapp.rc2"  // non-Visual C++ edited resources
#include "second.rc"  // THE SECOND .RC FILE

#include "afxres.rc"  // Standard components
#include "afxprint.rc"  // printing/print preview resources

结果如下图阐释:

   RESOURCE.H     AFXRES.H                    
          \       /                              
           \     /                                
          MYAPP.RC
              |                                
              |                              
        RES\MYAPP.RC2
        SECOND.RC  
        AFXRES.RC                   
        AFXPRINT.RC                 

使用编译时指令,可将您的 visual C++ 可编辑的和不可编辑的资源添加到多个 .RC 文件,其中的 “master” MYAPP.RC 执行 #include 其他 .RC 文件。如果您使用 Visual C++ 项目 .MAK 文件,则该项目应包含 “master” .RC 文件,以便所有 #include'd 资源编译应用程序。

Noneditable Visual C++ 文件的实现

AppWizard 创建的 RES \ MYAPP.RC2 文件是包含资源您不要意外地读取到 Visual C++ 然后将其写出具有格式设置信息丢失文件的示例。若要防止此操作,请将下面一行在 RES \ MYAPP.RC2 文件的开头:

#ifdef APSTUDIO_INVOKED
    #error this file is not editable by Visual C++
#endif //APSTUDIO_INVOKED

在 Visual C++ 生成 .RC 文件时,它定义 APSTUDIO_INVOKED 以及 RC_INVOKED。如果 AppWizard 创建的文件结构损坏, Visual C++ 读取上面 #error 行,它报告一个错误中止 .RC 文件的读取。

多个 visual C++ 编辑器的 .RC 文件共享的托管符号

两个问题,当您分离您的资源添加到您在 Visual C++ 若要单独编辑的多个 .RC 文件:

  • 您可能希望共享在多个 .RC 文件中的符号。

  • 您需要帮助 Visual C++ 避免进行相同的数值 ID 到清单的资源 (符号)。

下图阐释 .RC 的组织和。H 文件相关的第一个问题:

              MYAPP.RC
             /         \
            /           \
MYSTRS.H   / MYSHARED.H  \  MYMENUS.H
     \    /    /      \   \    \
      \  /    /        \   \    \
   MYSTRS.RC           MYMENUS.RC

在此示例中,字符串资源文件资源文件, MYSTRS.RC 保存,并且,菜单在另一个, MYMENUS.RC 保留。某些符号,如命令的,可能需要共享在两个文件之间。例如, ID_TOOLS_SPELL 可能是咒语项的菜单命令 ID 在 " 工具 " 菜单上;还可以位于应用程序的主窗口状态栏的结构显示的命令提示处的字符串 ID。

ID_TOOLS_SPELL 符号在共享的头文件, MYSHARED.H. 保留。手动维护该共享的头文件与文本编辑器;Visual C++ 不直接进行编辑。使用 资源包括 命令,在两个资源文件 MYSTRS.RC 和 MYMENUS.RC,可以在只读指令指定 #include MYSHARED.H 为, MYAPP.RC,如前面所述。

预期将共享的符号是最方便,在您尝试使用它标识所有资源。请将符号添加到共享的头文件,因此,如果您还没有 #include'd 共享的头文件在 .RC 文件的只读符号指令,在使用之前进行处理。如果您没有预料此类共享符号,则必须手动 (使用文本编辑器) 从 MYMENUS.H 移动符号的 #define 语句添加到 MYSHARED.H 在使用之前在 MYSTRS.RC。

当您管理多个 .RC 文件中的符号,还必须帮助 Visual C++ 避免进行相同的数值 ID 到清单的资源 (符号)。对于任何给定的 .RC 文件, Visual C++ 增量分配在四 ID 字段中的每一的 ID。在编辑会话之间,它在每个分配在符号头文件的字段。 .RC 文件的 Visual C++ 记录最后一个 ID。这就是 " APS_NEXT 值是空 (新建) .RC 文件:

#define _APS_NEXT_RESOURCE_VALUE  101
#define _APS_NEXT_COMMAND_VALUE   40001
#define _APS_NEXT_CONTROL_VALUE   1000
#define _APS_NEXT_SYMED_VALUE     101

_APS_NEXT_RESOURCE_VALUE 用于对话框资源,菜单资源将使用,等的下一个符号值。资源符号值的有效范围为 1 到 0x6FFF。

_APS_NEXT_COMMAND_VALUE 是为命令确定要使用的下一个符号值。命令符号值的有效范围是 0x8000 到 0xDFFF。

_APS_NEXT_CONTROL_VALUE 用于对话框控件将使用的下一个符号值。对话框控件符号值的有效范围为 8 到 0xDFFF。

_APS_NEXT_SYMED_VALUE 是使用在符号浏览器时,的新命令将发出的下一个符号值,当您手动进行符号值。

,当创建新的 .RC 文件时, Visual C++ 以略微该的最大值最低值的合法。AppWizard 还将初始化这些值传递给操作适合于 MFC 应用程序。有关 ID 值范围的更多信息,请参见 技术说明 20

现在,则即使在每次创建新的资源文件,对于项目, Visual C++ 定义相同 _APS_NEXT_ 值。这意味着,如果您将在两个不同 .RC 文件的多个对话框,同一个 #define 值可能会分配给不同的对话框。例如,在第一个 .RC 文件的 IDD_MY_DLG1 可能立刻分配相同, 101,为 IDD_MY_DLG2 .RC 文件。

为了避免这种情况,您应保留单独的数值范围 ID 四个字段中的每一个在单个 .RC 文件中。通过手动更新在每个元素的 _APS_NEXT 值执行此 .RC 文件中启动添加资源的 before 。例如,因此,如果第一个 .RC 文件使用默认 _APS_NEXT 值,则可能希望进行以下 _APS_NEXT 值赋给第二个 .RC 文件:

#define _APS_NEXT_RESOURCE_VALUE  2000
#define _APS_NEXT_COMMAND_VALUE   42000
#define _APS_NEXT_CONTROL_VALUE   2000
#define _APS_NEXT_SYMED_VALUE     2000

当然,可能会 Visual C++ 将在第一 .RC 文件的许多 ID 为第二个 .RC 文件以开始重叠这些保留的数值。您应保留足够大的大小,以便不会发生。

在 .RC, .CPP 之间的管理依赖项,和。H 文件

在 Visual C++ 保存一 .RC 文件时,它还会保存到相应的 RESOURCE.H 文件中的符号更改。引用在 .RC 文件中的资源的任何一 .CPP 文件必须 #include RESOURCE.H 文件,通常从项目的主头文件内。这将导致一个意外的副作用由于浏览源文件头依赖项的开发环境 (ide) 项目管理。在添加在 Visual C++ 时的新符号, #include RESOURCE.H 需要重新编译的所有 .CPP 文件。

Visual C++,通过包括以下注释避免在 RESOURCE.H 的依赖项作为 RESOURCE.H 文件的第一行:

//{{NO_DEPENDENCIES}}

开发环境通过忽略对 RESOURCE.H 的更改解释此注释,以便依赖 .CPP 文件不需要重新编译。

Visual C++ 始终添加 //{}} NO_DEPENDENCIES 注释行添加到 .RC 文件,并在保存文件时。有时,这样就避免了 RESOURCE.H 的生成依赖项可能导致运行时错误检测不到在链接时。例如,因此,如果对资源使用符号浏览器将数值赋给符号,该资源不会正确地找到并不会加载在应用程序运行时,如果引用该资源的 .CPP 文件不重新编译。在这种情况下,应该显式重新生成您知道受上 RESOURCE.H 上的符号更改的影响或选择 Rebuild All的所有 .CPP 文件。如果您具有需要频繁更改资源的某个组的符号值,您可能会发现更方便且更安全地打开这些符号到一个单独的只读的头文件,如上述部分 包括附加的头文件所述。

Visual C++ 如何管理设置包括信息

如上所述,设置为 " 文件 " 菜单包含指令允许您指定信息分为三种:

  • 符号头文件

  • 只读符号指令

  • 编译时指令

下面描述 Visual C++ 如何维护在 .RC 文件中的此信息。您不需要此信息使用 Visual C++,但是,它可以增进您理解,以便您可以更加便自信地使用其中包括功能。

上述三种类型的每一个的设置在 .RC 文件中的信息存储为两种形式:(1) 作为 #include 或其他指令可解释由资源编译器和 (2) 为特定 TEXTINCLUDE 资源只能解释由 Visual C++。

TEXTINCLUDE 资源的目的是为了安全起见存储设置包括信息以容易地以 Visual C++ 中的 Set Includes 对话框的窗体中。TEXTINCLUDE 是 Visual C++ 定义的 资源类型 。Visual C++ 识别具有资源标识号 1、 2 和 3,这时特定 TEXTINCLUDE 资源:

TEXTINCLUDE 资源 ID

类型的设置包括信息

1

符号头文件

2

只读符号指令

3

编译时指令

三种类型的每一个的设置包括信息与该默认 MYAPP.RC 和 AppWizard 创建的 RESOURCE.H 文件声明,如下所述。之间的额外 \ 0 和 " " 标记开始,并块规 RC 语法需要指定单个零结尾的字符串和双引号字符。

符号头文件

资源编译器解释符号头文件信息的格式为 #include 语句:

#include "resource.h"

对应的 TEXTINCLUDE 资源是:

1 TEXTINCLUDE DISCARDABLE
BEGIN
   #resource.h\0"
END

只读符号指令

只读符号指令包括在 MYAPP.RC 顶部为以下形式可解释由资源编译器:

#include "afxres.h"

对应的 TEXTINCLUDE 资源是:

2 TEXTINCLUDE DISCARDABLE
BEGIN
   "#include ""afxres.h""\r\n"
   "\0"
END

编译时指令

编译时指令包括在 MYAPP.RC 结束时为以下形式可解释由资源编译器:

#ifndef APSTUDIO_INVOKED
///////////////////////
//
// From TEXTINCLUDE 3
//
#include "res\myapp.rc2"  // non-Visual C++ edited resources

#include "afxres.rc"  // Standard components
#include "afxprint.rc"  // printing/print preview resources
#endif  // not APSTUDIO_INVOKED

#ifndef APSTUDIO_INVOKED 指令指示 Visual C++ 跳过在编译时指令。

对应的 TEXTINCLUDE 资源是:

3 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""res\myapp.rc2""  // non-Visual C++ edited resources\r\n"
"\r\n"
"#include ""afxres.rc""  // Standard components\r\n"
"#include ""afxprint.rc""  // printing/print preview resources\r\n"
"\0"
END

请参见

其他资源

由Number "技术说明

技术说明按类别