使用 #resource 指令描述资源

要在编译后的程序版本中包含资源文件,请在源代码中使用 #resource 指令。根据文件类型的不同,该指令有不同的形式。无论如何,该指令都包含 #resource 关键字,后面跟一个常量字符串。

#resource "path_file_name"

#resource 命令指示编译器在生成的可执行程序中包含一个文件(二进制格式 ex5),该文件具有指定的名称和可选位置(编译时)。路径是可选项:如果字符串中只包含文件名,则会在编译后的源代码旁边的目录中搜索到。如果字符串中包含路径,则适用以下规则。

编译器会按以下顺序在指定路径下查找资源:

  • 如果路径前有反斜杠 '\\'(必须是双斜杠,因为单反斜杠是控制字符;特别是,'\' 用于换行符 '\r'、'\n' 和制表符 '\t'),则从终端数据目录内的 MQL5 文件夹开始搜索资源。
  • 如果没有反斜杠,则相对于注册该资源的源文件的位置搜索资源。

请注意,在包含资源路径的常量字符串中,必须使用双反斜杠作为分隔符。与文件系统中的路径不同,这里不支持正向单斜杠。

例如:

#resource "\\Images\\euro.bmp" // euro.bmp is in /MQL5/Images/
#resource "picture.bmp"        // picture.bmp is in the same directory,
                               // where the source file is (mq5 or mqh)
#resource "Resource\\map.bmp"  // map.bmp is in the Resource subfolder of the directory
                               // where the source file is (mq5 or mqh)

如果资源在 mqh 头文件中声明了相对路径,则该路径将被视为相对于该 mqh 文件,而不是相对于正在编译的程序的 mq5 文件。

资源路径中不允许使用子字符串 "..\\" 和 ":\\"。

例如,使用一些指令,你可以将所有必要的图片和声音直接放入 ex5 文件中。这样,在另一个终端运行这样的程序时,就不需要单独传输它们了。我们将在接下来的各节中讨论从 MQL5 中访问资源的编程方法。

常量字符串 "path_file_name" 长度不得超过 63 个字符。资源文件大小不能超过 128 Mb。资源文件在纳入可执行文件中之前会自动压缩。

资源由 #resource 指令声明后,可在程序的任何部分使用。资源名称将变为指令中指定的常量字符串,开头不加斜线(如果有),字符串内容前应加上资源的特殊符号(两个冒号,"::")。

下面我们将举例说明资源,并在注释中列出其名称。

#resource "\\Images\\euro.bmp"          // resource name - ::Images\\euro.bmp
#resource "picture.bmp"                 // resource name - ::picture.bmp
#resource "Resource\\map.bmp"           // resource name - ::Resource\\map.bmp
#resource "\\Files\\Pictures\\good.bmp" // resource name - ::Files\\Pictures\\good.bmp
#resource "\\Files\\demo.wav";          // resource name - ::Files\\demo.wav"
#resource "\\Sounds\\thrill.wav";       // resource name - ::Sounds\\thrill.wav"

在后续的 MQL 代码中,可以按如下方式引用这些资源(在此,我们只知道 ObjectSetStringPlaySound 函数,但还有其他选项,如 ResourceReadImage,将在后续各节中介绍)。

ObjectSetString(0bitmap_nameOBJPROP_BMPFILE0"::Images\\euro.bmp");
...
ObjectSetString(0my_bitmapOBJPROP_BMPFILE0"::picture.bmp");
...
ObjectSetString(0bitmap_labelOBJPROP_BMPFILE0"::Resource\\map.bmp");
ObjectSetString(0bitmap_labelOBJPROP_BMPFILE1"::Files\\Pictures\\good.bmp");
...
PlaySound("::Files\\demo.wav");
...
PlaySound("::Sounds\\thrill.wav");

需要注意的是,将资源中的图像设置为 OBJ_BITMAP 和 OBJ_BITMAP_LABEL 对象时,不能手动更改 OBJPROP_BMPFILE 属性的值(在对象的属性对话框中)。

请注意,默认情况下,PlaySound 函数会相对于终端数据目录下的 Sounds 文件夹(或其子文件夹)设置 wav 文件。同时,如果资源(包括声音资源)在路径中带有斜线,则会在 MQL5 目录中搜索。因此,在上面的示例中,"\\Sounds\\thrill.wav" 字符串指的是 MQL5/Sounds/thrill.wav 文件,而不是相对于数据目录的 Sounds/thrill.wav(确实有一个包含标准终端声音的 Sounds 目录)。

上面讨论的 #resource 指令的简单语法只允许描述图像资源(BMP 格式)和声音资源(WAV 格式)。试图将不同类型的文件描述为资源时,会出现“未知资源类型”错误。

经过 #resource 指令处理后,文件实际上已嵌入可执行二进制程序,并可通过资源名称访问。此外,还应注意此类资源的一个特殊属性,即它们可以从其他程序中公开获取(下一节将详细介绍)。

MQL5 还支持在程序中嵌入文件的另一种方式:以 资源变量一节中显示了相关示例。此方法使用 #resource 指令的扩展语法,不仅可以连接 BMP 或 WAV 文件,还可以连接其他文件,例如文本或结构体数组。

我们将在后面几节分析连接资源的实际例子。