Easy Canvas (iCanvas) – library MetaTrader 4

The library and iCanvas class simplify writing programs using Canvas.

Here is an example of a simple indicator using this library.

In this example, the indicator body features no function for processing OnChartEvent events. But it may also be present.


#property indicator_chart_window
#property strict
#include <CanvasiCanvas.mqh>
//+------------------------------------------------------------------+
int OnInit()
  {
   EventSetMillisecondTimer(30);
   ChartSetInteger(0,CHART_CROSSHAIR_TOOL,false);  // turn off the crosshair
   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason) {if(reason<2) {ChartSetInteger(0,CHART_CROSSHAIR_TOOL,true); ChartRedraw();}}
//+------------------------------------------------------------------+
void  OnTimer()
  {
   static int X=0;
   static int Y=0;
   if(X!=W.MouseX || Y!=W.MouseY)
     {
      Canvas.Erase(0);
      // Draw a blurry spot
      for(int ix=-20;ix<=20;ix++) for(int iy=-20;iy<=20;iy++)
        {
         double p=sqrt(ix*ix+iy*iy)/20.0;
         if(p>1) p=1;
         uchar P=(uchar)Round((1.0-p)*255.0);
         Canvas.PixelSet(W.MouseX+ix,W.MouseY+iy,ARGB(P,100,0,200));
        }
      //  Display the information block
      int Y1=(int)Canvas.Y(Canvas.Close(W.MouseX));  // Y coordinate - Close price at the location of the mouse pointer.
      Canvas.FillRectangle(W.MouseX,Y1,W.MouseX+140,Y1+67,0xA0808080);
      Canvas.TextPosition(W.MouseX+5,Y1+2);
      Canvas.CurentFont("Arial",14,16,clrWhite);
      Canvas.Comm("Close = "+DoubleToString(Canvas.Close(W.MouseX),_Digits));
      Canvas.Comm("Bar = "+DoubleToString(W.MouseBar,2));
      Canvas.Comm(TimeToString(W.MouseTime,TIME_DATE|TIME_SECONDS));
      Canvas.Comm("SubWindow = "+string(W.MouseSubWin));
      //  Crosshairs
      Canvas.LineHorizontal(0,W.Width-1,W.MouseY,~W.Color);
      Canvas.LineVertical(W.MouseX,0,W.Height-1,~W.Color);
      int Ym=(W.MouseY>W.Height/2)?(W.MouseY-16):(W.MouseY+2);
      int Xm=(W.MouseX< W.Width/2)?(W.MouseX+4):(W.MouseX-105);
      Canvas.TextOut(W.Width-50,Ym,DoubleToString(W.MousePrice,_Digits),~W.Color);
      Canvas.TextOut(Xm,W.Height-16,TimeToString(W.MouseTime,TIME_DATE|TIME_SECONDS),~W.Color);

      Canvas.Update();
      X=W.MouseX; Y=W.MouseY;
     }
  }
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
   return(rates_total);
  }

struct Window: 

struct Window
  {
   long              ChartId;     // current window identifier
   uint              Color;       // window background color
   int               Width;       // window width
   int               Height;      // window height
   int               height[];    // sub_windows height
   int               Left_bar;    // number of the leftmost bar in the window
   double            Right_bar;   // number of the rightmost bar in the window
   double            Total_bars;  // the maximum number of bars in the window
   int               BarsInWind;  // number of visible bars in the window
   double            Y_min;       // The minimum value of the price in the window
   double            Y_max;       // The maximum value of the price in the window
   double            dy_pix;      // price change for one pixel
   int               dx_pix;      // changing the number of bars per pixel
   int               MouseX;      // coordinate X of the current position of the mouse pointer
   int               MouseY;      // coordinate Y of the current position of the mouse pointer
   double            MouseBar;    // the current bar position of the mouse pointer 
   double            MousePrice;  // the current price of the mouse pointer
   datetime          MouseTime;   // the current time of the mouse pointer
   int               MouseSubWin; // number of the subwindow in which the mouse pointer is located
   int               WindowsTotal;// total subwindows, including the main window
   int               SubWin;      // current subwindow
   datetime          time[];      // array of opening time of all visible bars in the window
  };

iCanvas class:

Alternative:  Tolerance for High Indicator - indicator MetaTrader 4
class iCanvas : public CCanvas
  {
private:
   datetime          T[1];
   double            Pr[1];
   bool              FullWinCanvW; // using full window canvas by width
   bool              FullWinCanvH; // using full window canvas by height
public:
                     iCanvas(long chart_id=0,int Xpos=0,int Ypos=0,string Name="iCanvas",int width=0,int height=0,ENUM_COLOR_FORMAT formatCF=COLOR_FORMAT_ARGB_NORMALIZE,int subwin=-1);
                    ~iCanvas() { Destroy(); ChartRedraw();};
   double            X(double bar){return((double)W.Left_bar-bar)*W.dx_pix;}; //The X coordinate by the bar number. The bar number must be of type double, otherwise, the bar will be interpreted as time.
   double            X(datetime Time);                                        //The X coordinate by the time.
   double            Y(double Price) {if(W.dy_pix==0) W.dy_pix=1; return((W.Y_max-Price)/W.dy_pix); }; //The Y coordinate by the price.
   double            Price(int y)     {return (W.Y_max-y*(W.Y_max-W.Y_min)/W.Height);};       // Price by the Y coordinate
   double            Bar(int x) {return((double)W.Left_bar+1-(double)x/(double)W.dx_pix);};   // bar number by coordinate X                                                                      
   datetime          TimePos(int x);                                                          // time by coordinate X 
   double            Close(int x)     {CopyClose(_Symbol,_Period,int(Bar(x)),1,Pr); return Pr[0];};
   double            Open(int x)      {CopyOpen(_Symbol,_Period,int(Bar(x)),1,Pr); return Pr[0];};
   double            High(int x)      {CopyHigh(_Symbol,_Period,int(Bar(x)),1,Pr); return Pr[0];};
   double            Low(int x)       {CopyLow(_Symbol,_Period,int(Bar(x)),1,Pr); return Pr[0];};
   bool              FullWinCanvWidth()  {return FullWinCanvW;};                              // using full window canvas by width  
   bool              FullWinCanvHeight() {return FullWinCanvH;};                              // using full window canvas by height   
   void              Comm(string text) {TextOut(TextPosX,TextPosY,text,TextColor); TextPosY+=StepTextLine;}; // Print comment
   void              TextPosition(int x,int y) {TextPosX=x; TextPosY=y;};                                    // Setting the XY position for comment output in pixels
   void              CurentFont(string FontName="Courier New",int size=18,int LineStep=20,color clr=clrDarkOrchid,double transp=1.0);  // Set font options for comment. LineStep - step between lines. transp - transparency from 0 to 1                                                                                                                                        
   void              TextPosition(double x,double y); // Setting the XY position for outputting comments as a percentage of the width and height of the window
   void              Line(double x1,double y1,double x2,double y2,const uint clr);
   int               TextPosX;      // Position X for comment text
   int               TextPosY;      // Position Y for comment text
   int               StepTextLine;  // line spacing for comment
   uint              TextColor;     // Font color for comment
   ENUM_PROGRAM_TYPE ProgType;
   int               SubWin;
   long              Handle;
  };

If you do not need an instance of the Canvas class for the full window, you can delete it and (or) change it to a partial window.

Alternative:  TrendValue_HTF - indicator MetaTrader 5

For example:

delete Canvas;
Canvas= new iCanvas(0,0,"iCanvas",300,0);          // Only the left bar of a window 300 pixels wide is created. Resizing the window is controlled
// Canvas= new iCanvas(0,0,"iCanvas",0,300);       // Only the top bar of a window height of 300 pixels is created. Resizing the window is controlled
// Canvas= new iCanvas(200,100,"iCanvas",300,300); // A square of 300x300 pixels is created with a starting point at (200,100). Window resizing is not controlled.

You can also create new instances of the class and initialize them at the time of creation.

For example:

iCanvas C2(300,200,"Canvas2",200,150,COLOR_FORMAT_XRGB_NOALPHA,1);

Important note: Since by default, the color format with transparency COLOR_FORMAT_ARGB_NORMALIZE is used, then when specifying the color, you must take into account the high byte of transparency.

If you use color names, for example, clrRed, then the color will be absolutely transparent because the transparency byte will be 0.

Therefore, you must use the ColorToARGB function (for example, ColorToARGB (clrRed))

or specify the color explicitly with non-zero transparency:

-for example, 0xFFAABBCC (Hexadecimal color representation),

where:

FF -byte of transparency,

AA – is red bytes,

BB – is green bytes,

CC – is blue bytes.

P.S.: This library was developed for MQL5 and ported from MQL5 code. Therefore, for MQL4 it is not optimal.

MQL5 version is much faster.

    📈 ROBOTFX MetaTrader Expert Advisors and Indicators to maximize profits and minimize the risks