Обсуждение статьи "Изучаем класс 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;
 

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

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

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

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

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

"канвас" - создает стандартные  OBJ_BITMAP_LABEL или OBJ_BITMAP. В справке есть функции по их размещению на графике

 //+------------------------------------------------------------------+
//| Перемещает объект "Графическая метка"                            |
//+------------------------------------------------------------------+
bool BitmapLabelMove(const long   chart_ID=0,      // ID графика
                     const string name="BmpLabel", // имя метки
                     const int    x=0,             // координата по оси X
                     const int    y=0)             // координата по оси Y
  {
//--- сбросим значение ошибки
   ResetLastError();
//--- переместим объект
   if(!ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x))
     {
      Print(__FUNCTION__,
            ": не удалось переместить X-координату объекта! Код ошибки = ",GetLastError());
      return(false);
     }
   if(!ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y))
     {
      Print(__FUNCTION__,
            ": не удалось переместить Y-координату объекта! Код ошибки = ",GetLastError());
      return(false);
     }
//--- успешное выполнение
   return(true);
  }

 Не заметил сразу обсуждение выше :) - собственно так же как и ZORDER, только Х и У 

 
MigVRN:

"канвас" - создает стандартные  OBJ_BITMAP_LABEL или OBJ_BITMAP. В справке есть функции по их размещению на графике

 Не заметил сразу обсуждение выше :) - собственно так же как и ZORDER, только Х и У 

Ага, спасибо, сработало... сам пробовал через ObjectMove...

Создаю панель с помощью канваса... нужно её передвинуть по возможности на графике...
Причина обращения: