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.