Canvas - это круто! - страница 84

 
Martin Moreno #:
Я хочу создать пользовательский интерфейс с помощью класса Canvas. Моя единственная проблема заключается в том, что я не знаю, как сделать приборную панель подвижной на графике.
Я много искал, но не нашел ни одного примера. Буду благодарен, если вы подскажете.


Вы можете начать с этой статьи: https: //www.mql5.com/en/articles/12751

Improve Your Trading Charts With Interactive GUI's in MQL5 (Part I): Movable GUI (I)
Improve Your Trading Charts With Interactive GUI's in MQL5 (Part I): Movable GUI (I)
  • www.mql5.com
Unleash the power of dynamic data representation in your trading strategies or utilities with our comprehensive guide on creating movable GUI in MQL5. Dive into the core concept of chart events and learn how to design and implement simple and multiple movable GUI on the same chart. This article also explores the process of adding elements to your GUI, enhancing their functionality and aesthetic appeal.
 
Samuel Manoel De Souza #:

Вы можете начать с этой статьи: https: //www.mql5.com/en/articles/12751

Отлично... Спасибо большое!

 
Martin Moreno #:
Я хочу создать пользовательский интерфейс с помощью класса Canvas. Моя единственная проблема заключается в том, что я не знаю, как сделать приборную панель подвижной на графике.
Я много искал, но не нашел ни одного примера. Буду благодарен, если вы подскажете.


Я уже приводил пример 4 года назад :))

Форум о трейдинге, автоматических торговых системах и тестировании торговых стратегий

как преобразовать все объекты в 1 объект

Николай Семко, 2019.10.05 22:39

Действительно, Canvas - это решение.

И Canvas намного проще, чем кажется на первый взгляд.

Вот примитивный пример индикатора (MQL5 & MQL4) с одним объектом OBJ_BITMAP_LABEL, в котором много окон.

#property indicator_chart_window
#include <Canvas\iCanvas.mqh> //https://www.mql5.com/ru/code/22164 - MQL5
                              //https://www.mql5.com/en/code/23840 - MQL4

struct win {
   int               x;
   int               y;
   int               width;
   int               height;
   uint              clr;
};
win wnd[30];
int OnInit() {
   for (int i=0; i<ArraySize(wnd); i++) {
      wnd[i].width=rand()%200+70;
      wnd[i].height=rand()%150+50;
      wnd[i].x=rand()%(W.Width-wnd[i].width);
      wnd[i].y=rand()%(W.Height-wnd[i].height);
      wnd[i].clr=ARGB(255,rand()%150+100,rand()%150+100,rand()%150+100);
   }
   ShowAllWind();
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+

int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) {
   return(rates_total);
}

//+------------------------------------------------------------------+

void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam) {
   static bool click = false;
   static int x_mouse=0, y_mouse=0;
   static int focus=-1, xfocus=0, yfocus=0;
   int x=(int)lparam;
   int y=(int)dparam;
   if (sparam!="1" && click) focus=-1;
   if (sparam=="1" && !click) {
      focus=-1;
      for (int i=ArraySize(wnd)-1; i>=0; i--) {
         if (wnd[i].x<x && wnd[i].y<y && wnd[i].x+wnd[i].width>x && wnd[i].y+20>y) {
            focus=i;
            xfocus=x;
            yfocus=y;
            break;
         }
      }
      if (focus>=0) ChartSetInteger(0,CHART_MOUSE_SCROLL,false);
      else ChartSetInteger(0,CHART_MOUSE_SCROLL,true);
   }
   click=(sparam=="1")?true:false;
   if (id==CHARTEVENT_MOUSE_MOVE && focus>=0) {
      wnd[focus].x+=x-xfocus;
      wnd[focus].y+=y-yfocus;
      xfocus=x;
      yfocus=y;
      ShowAllWind();
   }
   if (id==CHARTEVENT_CHART_CHANGE) ShowAllWind();
}

//+------------------------------------------------------------------+

void ShowAllWind() {
   Canvas.Erase();
   for (int i=0; i<ArraySize(wnd); i++) {
      Canvas.FillRectangle(wnd[i].x,wnd[i].y,wnd[i].x+wnd[i].width,wnd[i].y+wnd[i].height,ARGB(255,GETRGBR(wnd[i].clr)*0.5,GETRGBG(wnd[i].clr)*0.5,GETRGBB(wnd[i].clr)*0.5));
      Canvas.FillRectangle(wnd[i].x+3,wnd[i].y+23,wnd[i].x+wnd[i].width-3,wnd[i].y+wnd[i].height-3,wnd[i].clr);
      Canvas.FillRectangle(wnd[i].x+3,wnd[i].y+3,wnd[i].x+wnd[i].width-3,wnd[i].y+20,ARGB(255,GETRGBR(wnd[i].clr)*0.7,GETRGBG(wnd[i].clr)*0.7,GETRGBB(wnd[i].clr)*0.7));
   }
   Canvas.Update();
}
//+------------------------------------------------------------------+

В этой новой статье - еще один вариант реализации информационных панелей.

https://www.mql5.com/ru/articles/13179

Файлы:
 
Nikolai Semko #:
Вот например набросал скрипт, который это наглядно демонстрирует. Справа этот быстрый алгоритм, а слева мой (где-то в 4-10 раз медленее).
Nikolai Semko, привет. В этом примере https://www.mql5.com/ru/forum/227736/page66#comment_20456641 ты продемонстрировал изменение размера Bmp (уменьшение).

У меня получается уменьшать картинку Bmp, но полотно остаётся того-же размера. По той же причине я не могу увеличить картинку, она обрезается изначальными размерами, т.е. размером полотна.

В массивах не до конца разобрался, так что можешь мне объяснить, а лучше показать пример кодом:

1. Увеличение картинки

2. Полотно равное размеру картинки, если мы её уменьшили или увеличили.

Спасибо.

 
Vitaliy Kuznetsov #:
Nikolai Semko, привет. В этом примере https://www.mql5.com/ru/forum/227736/page66#comment_20456641 ты продемонстрировал изменение размера Bmp (уменьшение).

У меня получается уменьшать картинку Bmp, но полотно остаётся того-же размера. По той же причине я не могу увеличить картинку, она обрезается изначальными размерами, т.е. размером полотна.

В массивах не до конца разобрался, так что можешь мне объяснить, а лучше показать пример кодом:

1. Увеличение картинки

2. Полотно равное размеру картинки, если мы её уменьшили или увеличили.

Спасибо.

Привет,
Есть функция Resize() в CCanvas. 
 
Vitaliy Kuznetsov #:

Круто и полезно. Ради интереса, это можно использовать в МТ4?

К сожалению в MQL4 нет возможности прикреплять ресурс как массив. Но все остальное работает.
Можно конечно реализовать через жёсткие бубны. Например, вставить PNG изображение в BMP файл, т.е в начало png добавить шапку BMP формата, а сам png передавать как растр bmp( т.е. если открыть такой BMP, то будет шум из цветных пикселей разной прозрачности). А потом прикрепить этот "bmp файл", как ресурс в MQL4. Это может понадобиться для маркета, чтобы ex4 уже содержал изображение более плотного формата png.
Для справки: png примерно в 10 раз меньше того же BMP изображения без потери качества, в добавок поддерживая полноценную прозрачность.
Правда сам bmp ресурс в ex5(ex4) файле хранится в уплотненном  формате, но не на порядок меньше. Надо проверить точно.
 

Доброго всем времени суток. Мне тоже интересен этот код. Но при использовании Resize() - не получается. Может как-то в другой последовательности надо.

 

 
Vladimir Nikolaychuk #:

Доброго всем времени суток. Мне тоже интересен этот код. Но при использовании Resize() - не получается. Может как-то в другой последовательности надо.

 

Хорошо, чуть позже дам пример.
Но я предпочитаю работать с одним холстом на весь чарт. Это оправдано в 95% случаев.
 
Nikolai Semko #:
Хорошо, чуть позже дам пример.
Но я предпочитаю работать с одним холстом на весь чарт. Это оправдано в 95% случаев.

Был-бы очень признателен за пример кода. Заранее спасибо...

 
Nikolai Semko #:
Хорошо, чуть позже дам пример.
Но я предпочитаю работать с одним холстом на весь чарт. Это оправдано в 95% случаев.

вот пример на основе библиотеки png.mql, когда при движении мышки меняется положение canvas и меняется его размер. Если указатель мышки находится по центру по горизонтали, то это соответствует оригинальному размеру изображения, если левее -уменьшение, правее - увеличение масштаба.
Только мне пришлось в png.mql переменные C и _С перебросить из private в public. Поэтому необходимо перезаписать эту библиотеку, если она уже установлена.
В этом примере есть два режима работы (input переменная bool resize_canvas):

  • с изменением размера Canvas каждый раз при изменении размера изображения
  • без  изменением размера Canvas  при изменении размера изображения. Изначальный размер Canvas устанавливается равным максимальному возможному размеру изображения по логике работы. 
К сожалению, в первом режиме в MQL5 сидит древний баг моргания изображения, который лечится только одним способом - не менять размер canvas. Все мои попытки изменить функцию CCanvas.Resize() ни к чему не превели. Все также моргает. Может у кого-то получится :))
Именно поэтому предпочитаю использовать один холст на весь экран!

#define MAX_ZOOM 2
#include <Canvas\png.mqh> //https://www.mql5.com/en/code/45439
CPng img("cubes.png"); // Get PNG from a file, create a canvas and display it on the screen at coordinates (X=500, Y=100)

input bool resize_canvas = false;
int chart_width,chart_height;


//+------------------------------------------------------------------+
int OnInit() {
   img.Resize(resize_canvas?10:img.width*MAX_ZOOM); // формируем массив _bmp[] максимального размера в режиме без изменения размера canvas
   ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,true);
   chart_width = (int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);
   chart_height = (int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);
   img._CreateCanvas(chart_width/3, chart_height/3);
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
}
//+------------------------------------------------------------------+
void OnTick() {
}
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam) {
   if (id == CHARTEVENT_MOUSE_MOVE) {
      double new_width = img.width*(MAX_ZOOM*(double)lparam/chart_width);
      img.Resize(new_width);
      if (resize_canvas) { // режим с изменением размера canvas  Моргает!!!
         img._C.Resize(img._width,img._height);
         ArrayCopy(img._C.m_pixels,img._bmp);
      } else {  // режим без изменения размера canvas         не Мограет!!!
         img._C.Erase(0x00FFFFFF);
         for(int i =0; i++<img._height;) ArrayCopy(img._C.m_pixels,img._bmp,int(i*img.width*MAX_ZOOM),i*img._width,img._width);
      }
      img._C.Update();
      img._MoveCanvas(int(lparam)/5, int(dparam)/5);
   }
}



PNG
PNG
  • www.mql5.com
Forget about BMP files like a bad dream. Thanks to this library, you can now use the PNG format, which has a number of advantages, such as being more compact without losing image quality and maintaining transparency.
Файлы:
Причина обращения: