Вивчаємо клас ccanvas
Зміст
Малювати в терміналі MetaTrader 5 нескладно, потрібно знати тільки кілька нюансів. Наприклад, як влаштований сам екран терміналу. Точніше, нас буде цікавити, яким чином відбувається виведення графіки на екран терміналу. Адже на екрані сам графік може відображатися на задньому фоні, а може відображатися і на передньому плані. Від такого розташування буде залежати висновок кольору на екран. Деякі графічні об'єкти при виведенні на екран можуть змінювати колір в області перетину.
Перш ніж приступити до безпосереднього малювання за допомогою класу CCanvas. потрібно дізнатися деякі визначення, пов'язані з обробкою кольору. Наприклад, що таке прозорість і що таке альфа-канал.
Реалізація прозорості я взагалі вважаю найголовнішою технологією, за допомогою якої можна оживити картинку. Наприклад, за допомогою прозорості можна реалізувати більш красивий інтерфейс - з плавним перетіканням кольору або з тінню. Тінь додасть обсяг графічного об'єкту і візуально пом'якшить краю об'єкта.
1. Прозорість (альфа-канал)
Ми живемо в тривимірному світі і сприймаємо все предмети навколо нас об'ємними. Обсяг оточуючих нас предметів ми звикли бачити або навіть відчувати. У тривимірному світі ми можемо розрізняти, який з об'єктів розташований ближче або далі від нас.
При цьому деякі предмети можуть бути напівпрозорими. Для прикладу візьмемо прозорий скляний стакан з налитої в нього напівпрозорої рідиною на синьому тлі. Через стакан з рідиною проглядається задній синій фон. Причому від ступеня прозорості рідини залежить деталізація фону.

Мал. 1. Звичний погляд на обсяг
Прозорість в даному прикладі не віртуальна і не ілюзорна. Прозорість в даному випадку сприймається як саме собою зрозуміле.
При відображенні зображення на комп'ютерному моніторі все інакше - піксельна матриця моніторів двомірна: зображення, що відображається матрицею, має висоту і ширину, але не має третього параметра - глибини. Саме тому немає можливості мати у своєму розпорядженні пікселі один над іншим - як би імітувати ситуацію: нижній піксель - це жовтий фон, верхній піксель - напівпрозорий стакан. Будь-яке зображення тривимірного і реалістичного об'єкта на моніторі - це ілюзія, яка досягається грою кольору і тіні.
Розглянемо приклад зображення, яке можна розділити на два шари: нижній шар - це синій фон і верхній шар - стакан з непрозорою рідиною. Як це виглядає на моніторі:

Мал. 2. Непрозорий стакан
На результуючому зображенні стакан абсолютно непрозорий. А ось для додавання (зміни) прозорості потрібно все кольору зображення перевести в ARGB-уявлення кольору.
2. ARGB-уявлення кольору
Про прозорість склянки я не забув. Детально це питання буде розглянуто у другій частині.
ARGB уявлення кольору - це 4 байтовий тип uint. в якому записані по порядку наступні значення: альфа-канал, червоний, зелений, блакитний. Тобто, для додання прозорості до кольору в форматі RGB додають додатковий байт із значенням прозорості - альфа-канал.
Значення альфа-каналу задається значенням від 0 (колір накладається пікселя з верхнього шару зовсім не змінює відображення нижчого пікселя нижнього шару) до 255 (колір накладається повністю і перекриває собою колір нижчого пікселя). Прозорість кольору в процентному вираженні обчислюється за формулою:
Тобто, чим менше значення альфа-каналу, тим більш прозорий колір. Значить, якщо відома прозорість, яку ми хочемо досягти, то значення alpha можна розрахувати так:
Для перетворення кольору в ARGB уявлення служить функція ColorToARGB (колір, alpha).
3. Схема малювання об'єктів в терміналі
Щоб краще розуміти, як відбувається обробка кольору, розглянемо схему взаємного розташування графічних об'єктів при двох варіантах настройки графіка: графік на задньому плані і графік зверху.
3.1. Графік на задньому плані
Перевірити цю настройку можна так: правий клік мишкою на графіку, далі вибрати у випадаючому меню пункт "Властивості." І перейти на вкладку "Загальні".

Мал. 4. Графік на задньому плані
Вікно графіка в терміналі складається з чотирьох шарів. На двох крайніх шарах ( "Задній план" і "Передній план") можна малювати:

Мал. 5. Схема вікна графіка
На задньому плані (тлі) і на передньому плані графічні об'єкти при малюванні накладаються один на одного відповідно до пори свого створення.
Тобто, в самому низу на шарі "Задній план" і на шарі "Передній план" будуть знаходиться самі "старі" графічні об'єкти. Поверх будуть накладатися більш "молоді" графічні об'єкти.

Мал. 6. Розташування об'єктів в залежності від часу створення
Не всі графічні об'єкти можуть накладатися повністю, без перефарбовування в місцях (або областях) перетину з нижчого рівня графічними об'єктами.
У таблиці нижче зібрані характеристики графічних об'єктів. а після таблиці буде роз'яснення, як накладаються об'єкти, які перефарбовуються в місцях перетину.
Табл. 1. Накладення і прозорість графічних об'єктів
На прикладі трьох об'єктів типу OBJ_RECTANGLE (прямокутники) розглянемо алгоритм перефарбування в місцях перетину об'єктів, які перефарбовуються (файл xor.mq5).
Скрипт (файл xor.mq5) встановлює білий колір фону (0xFFFFFF) і малює прямокутники №1 і №2 синім кольором (0x0000FF) з заливкою, прямокутник №3 відображається червоним кольором (0xFF0000) з заливкою.

Мал. 7. Перефарбовування. Графік на задньому плані
На малюнку вийшли дві області перетину, в яких колір був перефарбований:
- Область №1 - результуючий колір (0x000000) повністю прозорий, тому в області №1 видно неперекрашенние фон і графік;
- Область №2 - результуючий колір (0x00FF00).
Графічні об'єкти типу прямокутників при перетині перефарбовуються за алгоритмом Побітова операція АБО.
Для рис. 6 нижче дан приклад перефарбування квітів для обох областей:
Табл. 3. Побітове виключає АБО для Синій + Червоний + Білий
3.2. Графік на передньому плані
Коли для графіка увімкнено "Графік зверху", розташування шарів вікна графіка відрізняється від розташування, при якому графік знаходиться на задньому плані:

Мал. 8. Схема вікна графіка. Графік зверху
Коли увімкнено для графіка "Графік зверху" два шари для малювання "Передній план" і "Задній план" з'єднуються в один загальний шар. Цей загальний шар знаходиться в самому низу під шарами з барами і сіткою.
3.3. Перефарбування для "Графік зверху"
Як і для рис. 7, розглянемо алгоритм перефарбування в місцях перетину об'єктів, які перефарбовуються (файл xor.mq5).
Скрипт (файл xor.mq5) встановлює білий колір фону (0xFFFFFF) і малює прямокутники №1 і №2 синім кольором (0x0000FF) з заливкою, прямокутник №3 малюється червоним кольором (0xFF0000) з заливкою.

Мал. 9. Перефарбовування. Графік на передньому плані
Якщо порівняти рис. 7 і рис. 9, то видно, що області перетину перефарбовуються однаково.
4. Змішування кольорів. результуючий колір
Як я говорив вище, зображення прозорості на екрані монітора - це ілюзія. Гра кольору. Щоб змоделювати рис. 2 на моніторі, залишилося трохи - розібратися, а як власне колір з прозорістю відобразити на моніторі? Тобто, як розрахувати результуючий колір пікселя?
Нехай на білому тлі (це фон графіка в колірній схемі "Black On White") ми хочемо намалювати на канвасе червоний колір c альфа-каналом, рівним 128. У форматі ARGB цей колір буде мати запис 0x80FF0000. Для розрахунку результуючого кольору потрібно розрахувати колір кожного з каналів (Red, Green, Blue).
Формула розрахунку результуючого кольору при накладенні кольору з альфа-каналом, нормалізованим до одиниці:
- result - результуюче значення інтенсивності колірного каналу. Якщо отримане значення більше 255, то повертається 255.
- background - значення колірного каналу фону.
- foreground - значення колірного каналу накладають картинки.
- alpha - значення альфа-каналу, нормалізоване до одиниці.
Розрахуємо результуючий колір згідно з формулою (1.3):
Альфа-канал, нормалізований до "1"
Компоненти кольору обробляються терміналом
Табл. 5. Способи обробки кольору при створенні кинувся
COLOR_FORMAT_ARGB_NORMALIZE дозволяє отримувати більш красиву картинку за рахунок обліку правильного накладення компонентів RGB. Розрахунок результуючого кольору при накладенні кольору з альфа-каналом відбувається за формулою (1.3).
COLOR_FORMAT_ARGB_RAW не виробляє контроль над переповненням RGB компонентів квітів і тому COLOR_FORMAT_ARGB_RAW швидший метод в порівнянні з COLOR_FORMAT_ARGB_NORMALIZE.
Формула розрахунку результуючого кольору при накладенні кольору з альфа-каналом, нормалізованому до одиниці, для методу COLOR_FORMAT_ARGB_RAW:
- result - результуюче значення інтенсивності колірного каналу. Якщо отримане значення більше 255, то повертається 255.
- background - значення колірного каналу фону.
- foreground - значення колірного каналу накладають картинки.
- alpha - значення альфа-каналу, нормалізоване до одиниці.
5. Ілюзія прозорості
Тепер можна приступити до практичної реалізації прозорості.
На графіку малюємо кілька прямокутників з заливкою (скрипт "xor.mq5"). Для наочності ілюстрації різних методів обробки кольору поверх графіка накладаємо по горизонталі три кинувся без їх взаємного перекриття.
Перший має метод обробки COLOR_FORMAT_XRGB_NOALPHA, другий - COLOR_FORMAT_ARGB_RAW і третій - COLOR_FORMAT_ARGB_NORMALIZE. Потім поступово змінюємо прозорість від 255 (повна непрозорість) до 0 (повна прозорість). Назвемо наш скрипт "Illusion.mq5".
Мал. 11. Робота скрипта illusion.mq5
5.1. Створення скрипта "Illusion.mq5"
Додані або змінені ділянки коду будуть виділятися кольором.
Поки що порожній шаблон скрипта:
Додамо опис скрипта, можливість вводити параметри при запуску скрипта і підключимо клас CCanvas - клас, завдяки якому ми і будемо малювати:
Для роботи скрипта потрібні будуть кілька змінних - висота і ширина графіка, висота і ширина кинувся, а також допоміжні змінні для малювання координат кинувся:
Для отримання ширини і висоти графіка скористаємося стандартними функціями.
Переходимо безпосередньо в OnStart ().
Для наочності на рис. 12 приведена схема розташування кинувся на графіку, а також позначення допоміжних змінних для координат кинувся:

Мал. 12. Координати на графіку
Отримаємо висоту і ширину графіка, а також розрахуємо допоміжні змінні для координат кинувся:
Маючи розраховані ширину і висоту кинувся, а також допоміжні координати можна приступити до малювання.
Далі змінимо тип void функції OnStart () на int і намалюємо на першому канвасе зафарбований прямокутник, текст з назвою методу обробки кольору на даному канвасе і зафарбовані окружність:
Зупинюся докладніше на останньому вставленому коді.
canvas_XRGB_NOALPHA.CreateBitmapLabel - Тут ми створили графічний ресурс, прив'язаний до об'єкта чарту.
Перший кинувся створений з режимом обробки зображення COLOR_FORMAT_XRGB_NOALPHA - компонента альфа-каналу при малюванні будуть ігноруватися.
Заповнюємо весь кинувся кольором в форматі ARGB c прозорістю alpha.
Так як для даного кинувся заданий режим обробки зображень COLOR_FORMAT_XRGB_NOALPHA - кинувся буде заповнений кольором без урахування альфа-каналу.
Виводимо текст - тип обробки зображення для даного кинувся. Колір тексту в форматі ARGB і альфа-каналом рівним 255, тобто колір тексту, що виводиться повністю непрозорий.
Виведений текст прив'язується і по горизонталі (TA_CENTER) і по вертикалі (TA_VCENTER) по центру прямокутника.
Малюємо зафарбований круг. Коло буде малюватися поверх кольору, яким ми заповнили кинувся (canvas_XRGB_NOALPHA.Erase (ColorToARGB (colr, alpha));).
Це зроблено для демонстрації того, що намальована на канвасе фігура (або область / точка) повністю стирає під собою нижчележачий малюнок на канвасе. Тобто, ніякого перефарбування на канвасе не буде, тому що останній висновок малюнка стирає повністю область під собою.
Якщо ми хочемо, щоб все намальоване відобразилося на екрані, потрібно оновити екран.
Аналогічно малюються інші два кинувся: другий кинувся з режимом відображення COLOR_FORMAT_ARGB_RAW і третій кинувся з режимом відображення COLOR_FORMAT_ARGB_NORMALIZE:
Кинувся і графіка всередині кинувся намальовані.
Тепер зробимо цикл, в якому буде змінюватися прозорість всього кинувся:
Зміна прозорості для всього кинувся виконується за допомогою рядків виду:
Після закінчення малювання потрібно прибрати за собою - видалити графічні ресурси.
Так як ми створювали графічний ресурс з прив'язкою до об'єкта чарту (метод CreateBitmapLabel), то видалення ресурсу виконаємо за допомогою методу Destroy () - заодно віддалиться і об'єкт чарту (Bitmap Label):
Скрипт, плавно змінює прозорість працює.
Зазначу, що відмінність режимів відображення COLOR_FORMAT_ARGB_RAW і COLOR_FORMAT_ARGB_NORMALIZE особливо добре видно, якщо скрипт запустити спочатку на білому тлі графіка, а потім на чорному тлі.
висновок
У статті були розглянуті основи роботи з кольором, ми дізналися, як малювати у вікні графіка. Також розглянули основи роботи з класом CCanvas Стандартної бібліотеки, дізналися про формат представлення кольору з прозорістю ARGB.
Це тільки початок на шляху до створення дійсно гарних ефектів для графічних об'єктів в терміналі MetaTrader 5. Ще раз хочу зупинитися на прозорості: саме часткова прозорість надає найбільш красиву форму для обкантовок графічних об'єктів. В силу двухмерности моніторів прозорість в графіку - це ілюзія, що досягається обробкою накладається піскелей.