- Описание ресурсов с помощью директивы #resource
- Разделяемое использование ресурсов разных MQL-программ
- Ресурсные переменные
- Подключение пользовательских индикаторов как ресурсов
- Динамическое создание ресурсов: ResourceCreate
- Удаление динамических ресурсов: ResourceFree
- Чтение и модификация данных ресурса: ResourceReadImage
- Сохранение изображений в файл: ResourceSave
- Шрифты и вывод текста в графические ресурсы
- Прикладное применение графических ресурсов в трейдинге
Ресурсные переменные
Директива #resource имеет специальную форму, с помощью которой внешние файлы можно объявлять в виде ресурсных переменных и обращаться к ним внутри программы, как к обычным переменным соответствующего типа. Формат объявления таков:
#resource "путь_имя_файла" as тип_ресурсной_переменной имя_ресурсной_переменной |
Вот несколько примеров объявлений:
#resource "data.bin" as int Data[] // массив типа int с данными из файла data.bin
|
Дадим несколько пояснений. Ресурсные переменные являются константами (их нельзя модифицировать в коде MQL5). Для редактирования, например, изображений перед выводом на экран, следует создавать копии ресурсных переменных-массивов.
Для текстовых файлов (ресурсов типа string) производится автоматическое определение кодировки по наличию BOM-заголовка. Если BOM отсутствует, то кодировка определяется по содержимому файла. Поддерживаются файлы в кодировках ANSI, UTF-8 и UTF-16. При чтении данных из файлов все строки переводятся в Unicode.
Использование ресурсных строковых переменных может существенно облегчить написание программ, которые основаны не только на чистом MQL5, но и дополнительных технологиях. Например, вы можете написать код OpenCL (который поддерживается в MQL5 в качестве расширения) в отдельном файле, а затем включить его в виде строки в ресурсы MQL-программы. В примере большого эксперта мы уже применяли строки-ресурсы для подключения HTML-шаблонов.
Для изображений введен специальный тип bitmap, имеющий несколько особенностей.
Тип bitmap описывает одну точку или пиксель изображения и имеет представление 4-x байтового беззнакового целого (uint). Внутри пикселя содержатся 4 байта, которые соответствуют компонентам цвета в формате ARGB или XRGB (одна буква — один байт), где R — красный (Red), G — зеленый (Green), B — синий (Blue), A — прозрачность (альфа-канал), X — байт игнорируется (без прозрачности). Прозрачность может использоваться для различных эффектов при наложении изображений на график и друг на друга.
Определение форматов ARGB и XRGB мы изучим в разделе про динамическое создание графических ресурсов (см. ResourceCreate). Например, для ARGB число в шестнадцатеричном представлении 0xFFFF0000 задает полностью непрозрачный пиксель (старший байт равен 0xFF) красного цвета (следующий байт также равен 0xFF), а следующие байты для зеленой и синей компоненты равны нулю.
Важно отметить, что кодирование цвета пикселей отличается от байтового представления типа color. Напомним, что значение типа color можно записать в шестнадцатеричном виде так: 0x00BBGGRR, где BB, GG, RR — это соответственно синяя, зеленая и красная компоненты (в каждом байте значение 255 дает максимальную интенсивность компоненты). При аналогичной записи пикселя налицо обратный порядок байтов: 0xAARRGGBB. Полная прозрачность получается, когда старший байт (здесь обозначен AA) равен 0, а значение 255 — сплошной цвет. Для перевода цвета color в ARGB формат имеется функция ColorToARGB.
Файлы формата BMP могут иметь различные способы кодирования (если вы их создаете или редактируете в каком-либо редакторе, уточните этот вопрос в документации этой программы). Ресурсы MQL5 поддерживают не все существующие способы кодирования. Проверить, поддерживается ли конкретный файл, можно с помощью функции ResourceCreate. Указание файла неподдерживаемого формата BMP в директиве приведет к ошибке компиляции.
При загрузке файла с 24-битным кодированием цвета для всех пикселей компонента альфа-канала устанавливается в значение 255 (непрозрачный).
При загрузке файла с 32-битным кодированием цвета без альфа-канала, также подразумевает отсутствие прозрачности, то есть для всех пикселей изображения компонента альфа-канала устанавливается в значение 255.
При загрузке файла с 32-битным кодированием цвета с альфа-каналом никаких манипуляций с пикселями не происходит.
Изображения можно описывать как одномерными, так и двумерными массивами. Это влияет только на способ адресации, но объем занимаемой памяти будет одинаковым. В обоих случаях размеры массива автоматически устанавливаются на основе данных из bmp-файла. Размер одномерного массива будет равен произведению высоты на ширину картинки (height * width), а двумерный массив получит раздельные измерения [height][width]: первый индекс — номер строки, второй — точка в строке.
Внимание! При объявлении ресурса в привязке к ресурсной переменной обращаться к ресурсу можно только через эту переменную, а стандартный способ чтения через имя "::имя_ресурса" (или в более общем случае "путь_имя_файла.ex5::имя_ресурса") больше не работает. Это также означает, что подобные ресурсы нельзя использовать, как разделяемые, из других программ.
Рассмотрим в качестве примера два индикатора: оба являются безбуферными. Данный тип MQL-программ выбран только из соображений удобства (потому что их можно бесконфликтно наложить на график в дополнение к другим индикаторам (эксперт потребовал бы график без другого эксперта), а кроме того они остаются на графике и доступны для последующего изменения настроек, в отличие от скриптов).
Индикатор BmpOwner.mq5 содержит описание трех ресурсов:
- изображение "search1.bmp" с простой директивой #resource и потому доступное из других программ;
- изображение "search2.bmp" в виде ресурсной переменной-массива типа bitmap и потому недоступное извне;
- текстовый файл "message.txt" как ресурсная строка для вывода предупреждения пользователю;
Обе картинки никак не используются внутри данного индикатора. Строка с предупреждением требуется в функции OnInit для вызова Alert, поскольку индикатор не предназначен для самостоятельного применения, а только выступает в качестве поставщика ресурса-картинки.
Если ресурсная переменная не используется в исходном коде, компилятор может вообще не включить ресурс в двоичный код программы, но это не касается изображений.
#resource "search1.bmp"
|
Все три файла расположены в том же каталоге, где и исходный код индикатора — MQL5/Indicators/MQL5Book/p7/.
Если пользователь попробует запустить индикатор, тот выводит предупреждение и сразу же прекращает работу. Предупреждение содержится в ресурсной переменной-строке Message.
int OnInit()
|
Во втором индикаторе BmpUser.mq5, мы попытаемся использовать внешние ресурсы, заданные во входных переменных ResourceOff и ResourceOn, для отображения в объекте OBJ_BITMAP_LABEL.
input string ResourceOff = "BmpOwner.ex5::search1.bmp";
|
По умолчанию состояние объекта отключенное/отжатое ("Off") и для него берется картинка из предыдущего индикатора — "BmpOwner.ex5::search1.bmp". Этот путь и имя ресурса аналогичны полной записи "\\Indicators\\MQL5Book\\p7\\BmpOwner.ex5::search1.bmp". Краткая форма здесь допустима с учетом того, что индикаторы располагаются рядом друг с другом. Если вы впоследствии откроете диалог свойств объекта, то увидите там в полях Bitmap file (On/Off) именно полную запись.
Для нажатого состояния в ResourceOn предлагается прочитать ресурс "BmpOwner.ex5::search2.bmp" (посмотрим, что из этого выйдет).
В других входных переменных можно выбрать угол графика, относительно которого задается позиционирование картинки, и величина отступов по горизонтали и вертикали.
input int X = 25;
|
Непосредственно создание объекта OBJ_BITMAP_LABEL и установка его свойств, включая и имя ресурса в качестве картинки для OBJPROP_BMPFILE, выполняется в OnInit.
const string Prefix = "BMP_";
|
Напомним, что при указании картинок в OBJPROP_BMPFILE нажатое состояние обозначается модификатором 0, а отжатое (по умолчанию) — модификатором 1, что несколько неожиданно.
Обработчик OnDeinit удаляет объект при выгрузке индикатора.
void OnDeinit(const int)
|
Откомпилируем оба индикатора и запустим BmpUser.ex5 с параметрами по умолчанию. На графике должно появиться изображение графического файла search1.bmp (см. слева).
Нормальное (слева) и проблемное (справа) отображение графических ресурсов в объекте на графике
Если щелкнуть мышью на картинке, то есть переключить ей в нажатое состояние, программа попытается обратиться к ресурсу "BmpOwner.ex5::search2.bmp" (который недоступен из-за того, что к нему привязан ресурсный массив bitmap). В результате мы увидим красный квадрат, обозначающий пустой объект без картинки (см. выше, справа). Аналогичная ситуация будет всегда, если во входном параметре указывать путь или имя с заведомо несуществующим или неразделяемым ресурсом. Вы можете создать собственную программу, описать в ней ресурс, ссылающийся на какой-либо существующий bmp-файл, и затем указать во входных параметрах индикатора BmpUser — индикатор сможет вывести картинку на график.