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