Обсуждение статьи "Изучаем класс CCanvas. Реализация прозрачности графических объектов"

 

Опубликована статья Изучаем класс CCanvas. Реализация прозрачности графических объектов:

Надоела угловатая графика скользящих средних? Вы хотите рисовать в терминале что-то более красивое, чем простой прямоугольник с заливкой? Рисовать красиво в терминале можно. Для этого есть класс для создания пользовательской графики - CCanvas. С помощью этого класса можно реализовать прозрачность, смешивать цвета и получать иллюзию прозрачности при помощи наложения и смешивания цвета.

Рисовать в терминале MetaTrader 5 несложно, нужно знать только несколько нюансов. Например, как устроен сам экран терминала. Точнее, нас будет интересовать, каким образом происходит вывод графики на экран терминала. Ведь на экране сам график может отображаться на заднем фоне, а может отображаться и на переднем плане. От такого расположения будет зависеть вывод цвета на экран. Некоторые графические объекты при выводе на экран могут изменять цвет в области пересечения.

Прежде чем приступить к непосредственному рисованию с помощью класса CCanvas, нужно узнать некоторые определения, связанные с обработкой цвета. Например, что такое прозрачность и что такое альфа-канал.

Реализация прозрачности я вообще считаю самой главной технологией, с помощью которой можно оживить картинку. Например, с помощью прозрачности можно реализовать более красивый интерфейс – с плавным перетеканием цвета или с тенью. Тень придаст объем графическому объекту и визуально смягчит края объекта.

5. Иллюзия прозрачности

Теперь можно приступить к практической реализации прозрачности.

На графике рисуем несколько прямоугольников с заливкой (скрипт "xor.mq5"). Для наглядности иллюстрации разницы методов обработки цвета поверх графика накладываем по горизонтали три канваса без их взаимного перекрытия.

Первый имеет метод обработки COLOR_FORMAT_XRGB_NOALPHA, второй - COLOR_FORMAT_ARGB_RAW и третий - COLOR_FORMAT_ARGB_NORMALIZE. Затем постепенно меняем прозрачность от 255 (полная непрозрачность) до 0 (полная прозрачность). Назовем наш скрипт "Illusion.mq5".

Видео работы скрипта "Illusion.mq5":


Рис. 11. Работа скрипта illusion.mq5втор: Karputov Vladimir

 
Владимир, я в канвасах не силён. Вопрос такой. Есть канвас. На нём есть текстовая метка. Почему событие клика по метке терминал видит как событие клика по канвасу? Можно этот конфликт как-то разрешить?
 
denkir:
Владимир, я в канвасах не силён. Вопрос такой. Есть канвас. На нём есть текстовая метка. Почему событие клика по метке терминал видит как событие клика по канвасу? Можно этот конфликт как-то разрешить?
Давайте код. Будем смотреть.
 
denkir:
...

Для этого есть свойство, которым можно устанавливать приоритет:

OBJPROP_ZORDER - Приоритет графического объекта на получение события нажатия мышки на графике (CHARTEVENT_CLICK). По умолчанию при создании значение выставляется равным нулю, но при необходимости можно повысить приоритет. При наложении объектов друг на друга событие CHARTEVENT_CLICK получит только один объект, чей приоритет выше остальных. 

 

Код попозже скину. OBJPROP_ZORDER -для канваса врод как нельзя задать...

Нашёл, что у меня вызывает неправильную обработку... Есть 2 канваса, один наложен на другой. И сверху текстовая метка. Вот её-то и не видит OnChartEvent().

 
denkir:

Код попозже скину. OBJPROP_ZORDER -для канваса врод как нельзя задать...

Нашёл, что у меня вызывает неправильную обработку... Есть 2 канваса, один наложен на другой. И сверху текстовая метка. Вот её-то и не видит OnChartEvent().

Можно. Это ведь обычный объект типа OBJ_BITMAP_LABEL или OBJ_BITMAP.

 
tol64:

Можно. Это ведь обычный объект типа OBJ_BITMAP_LABEL или OBJ_BITMAP.

Точно. Спасибо.

Для этого нужно вытащить имя привязанного объекта чарта и задать ему приоритет.

Вот как-то так (отрывок из блока инициализации):

//--- создать 1-ый канвас
   if(!myCanvas1.CreateBitmapLabel("My canvas1",_X,_Y,Width,Height,COLOR_FORMAT_ARGB_RAW)) 
     {
      Print("Error creating base canvas: ",GetLastError());
      return INIT_FAILED;
     }
//--- отображение
   myCanvas1.Erase(XRGB(0x1F,0x1F,0x1F)); 
   myCanvas1.Update();
   string obj_name=myCanvas1.ChartObjectName();
   if(!ObjectSetInteger(0,obj_name,OBJPROP_ZORDER,0))
      return INIT_FAILED;
 

Здравствуйте, Владимир,

Спасибо за эту интересную статью.

В вашей таблице 3 есть небольшая ошибка.

С'255,0,255' 0xFF00FF 1111 1111 0000 0000 1111 1111


XOR
C'255,255,255' 0xFFFFFF 1111 1111 1111 1111 1111 1111 Белый (фон)


=
С'0,255,0' 0x00FF00 1111 1111 1111 0000 0000 0000
Должно быть :
0000 0000 1111 1111 0000 0000
Зеленый
 
angevoyageur:

Здравствуйте, Владимир,

Спасибо за эту интересную статью.

В вашей таблице 3 есть небольшая ошибка.

С'255,0,255' 0xFF00FF 1111 1111 0000 0000 1111 1111


XOR
C'255,255,255' 0xFFFFFF 1111 1111 1111 1111 1111 1111 Белый (фон)


=
С'0,255,0' 0x00FF00 1111 1111 1111 0000 0000 0000
Должно быть :
0000 0000 1111 1111 0000 0000
Зеленый
Спасибо за найденную ошибку.
 

Вопрос такой. Какая может быть лучшая реализация по передвижению канваса по графику? Что-то вроде метода:

bool CUserCanvas::Move(int _new_x,int _new_y);
 
denkir:

Вопрос такой. Какая может быть лучшая реализация по передвижению канваса по графику? Что-то вроде метода:

А какова цель перемещения? Может лучше перерисовывать рисунок на канвасе?