Canvas is cool! - page 84

 
Martin Moreno #:
I want to create a user interface with the Canvas class. My only problem is that I don't know how make the dashboard movable on chart.
I searched a lot but didn't find any example. I would appreciate if you could give a hint.


you could start by this article: 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 #:

you could start by this article: https://www.mql5.com/en/articles/12751

Great...Thanks a ton!

 
Martin Moreno #:
I want to create a user interface with the Canvas class. My only problem is that I don't know how make the dashboard movable on chart.
I searched a lot but didn't find any example. I would appreciate if you could give a hint.


I already gave you an example 4 years ago :))

Forum on trading, automated trading systems and testing trading strategies

how to convert all objects into 1 object

Nikolai Semko, 2019.10.05 22:39

Indeed, Canvas is the solution.

And Canvas is much easier than it seems at first glance.

Here is a primitive example of an indicator (MQL5 & MQL4) with one object OBJ_BITMAP_LABEL in which there are many windows.

#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();
}
//+------------------------------------------------------------------+

n this new article, another option for implementing Information panels.

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

Files:
 
Nikolai Semko #:
Here, for example, I have sketched a script that demonstrates it clearly. On the right is this fast algorithm, and on the left is mine (about 4-10 times slower).
.
Nikolai Semko, hi. In this example https://www.mql5.com/ru/forum/227736/page66#comment_20456641 you demonstrated Bmp resizing (shrinking).

I can reduce the Bmp picture, but the canvas remains the same size. For the same reason I can't enlarge the picture, it is cropped by the original size, i.e. the size of the canvas.

I don't fully understand arrays, so can you explain it to me, or better show me an example with code:

1. Image enlargement

2. A canvas equal to the size of the picture if we have reduced or enlarged it.

Thank you.

 
Vitaliy Kuznetsov #:
Nikolai Semko, hi. In this example https://www.mql5.com/ru/forum/227736/page66#comment_20456641 you have demonstrated Bmp resizing (reducing).

I can reduce the Bmp picture, but the canvas remains the same size. For the same reason I can't enlarge the image, it is cropped by the original size, i.e. the size of the canvas.

I don't fully understand arrays, so can you explain it to me, or better show me an example with code:

1. Image enlargement

2. A canvas equal to the size of the picture if we have reduced or enlarged it.

Thank you.

Hi,
There is a Resize() function in CCanvas.
 
Vitaliy Kuznetsov #:

Cool and useful. Just for interest, can this be used in MT4?

Unfortunately, in MQL4 there is no possibility to attach a resource as an array. But everything else works.
Of course, it can be implemented through hard tambourines. For example, insert a PNG image into a BMP file, i.e. add a BMP header to the beginning of the png, and pass the png itself as a bmp image (i.e. if you open such a BMP, there will be a noise of coloured pixels of different transparency). And then attach this "bmp file" as a resource in MQL4. This may be necessary for the market, so that ex4 already contains an image of a more dense png format.
For reference: png is about 10 times smaller than the same BMP image without loss of quality, in addition supporting full transparency.
True bmp resource in ex5(ex4) file is stored in a compacted format, but not by an order of magnitude less. It is necessary to check exactly.
 

Good day to all. I am also interested in this code. But when using Resize(), it does not work. Maybe it should be done in a different sequence.

 
Vladimir Nikolaychuk #:

Good day to all. I am also interested in this code. But when using Resize(), it does not work. Maybe it should be done in a different sequence.

Okay, I'll give you an example later.
But I prefer to work with one canvas for the whole chart. It's justified 95% of the time.
 
Nikolai Semko #:
Okay, I'll give you an example a little later.
But I prefer to work with one canvas for the whole chart. This is justified 95% of the time.

I would be very grateful for a code example. Thanks in advance...

 
Nikolai Semko #:
Okay, I'll give you an example a little later.
But I prefer to work with one canvas for the whole chart. This is justified 95% of the time.

Here is an example based on the png.mql library, when moving the mouse changes the position of the canvas and changes its size. If the mouse pointer is in the centre horizontally, it corresponds to the original size of the image, if to the left - zoom out, to the right - zoom in.
Only I had to rethrow variables C and _C in png.mql from private to public. So you need to overwrite this library if it is already installed.
This example has two modes of operation (input variable bool resize_canvas):

  • with Canvas resizing every time the image is resized
  • without resizing Canvas every time the image is resized. The initial size of Canvas is set equal to the maximum possible image size according to the logic of work.
Unfortunately, in the first mode in MQL5 there is an ancient bug of image blinking, which can be cured only in one way - not to change the canvas size. All my attempts to change the CCanvas.Resize() function did not lead to anything. Everything blinks the same way. Maybe someone can do it :)))
That's why I prefer to use one canvas for the whole screen!

#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.