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
#include <Canvas\iCanvas.mqh>
int OnInit()
{
EventSetMillisecondTimer(33);
ChartSetInteger(0,CHART_SHOW,true);
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));
Canvas.FillRectangle(W.MouseX,Y1,W.MouseX+140,Y1+67,0xA0808080);
Canvas.TextOut(W.MouseX+5,Y1+2,"Close = "+DoubleToString(Canvas.Close(W.MouseX),_Digits),0xFFFFFFFF);
Canvas.TextOut(W.MouseX+5,Y1+18,"Bar = "+DoubleToString(W.MouseBar,2),0xFFFFFFFF);
Canvas.TextOut(W.MouseX+5,Y1+34,TimeToString(W.MouseTime,TIME_DATE|TIME_SECONDS),0xFFFFFFFF);
Canvas.TextOut(W.MouseX+5,Y1+50,"SubWindow = "+string(W.MouseSubWin),0xFFFFFFFF);
// 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>16)?(W.MouseY-16):(W.MouseY+2);
int Xm=(W.MouseX<(W.Width-140))?(W.MouseX+4):(W.MouseX-125);
Canvas.TextOut(W.Width-76,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);
}
Library features:
- when connecting the library, one instance with the name Canvas of the iCanvas class derived from the CCanvas class is created immediately.
- the size of this instance matches the entire window. Further, when the window is resized, the canvas is automatically resized (except for scripts).
- using the OnChartEvent event handler function is optional.
- inside the library, there is also an instance of the Window structure named W. The window parameters (except for scripts) are located and automatically updated inside this structure.
Window structure:
struct Window
{
uint Color; // window background color
int Width; // window width
int Height; // window 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(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();};
double X(double bar);
double X(datetime Time) {return X((double)Ceil(W.Right_bar)+iBarShift(NULL,0,Time));};
double Y(double Price) {return((W.Y_max-Price)/W.dy_pix); };
double Bar(int x) {return((double)W.Left_bar+1-(double)x/(double)W.dx_pix);};
datetime TimePos(int x) {double B=Bar(x); CopyTime(_Symbol,_Period,Floor(B),1,T); return T[0]+int((double)PeriodSeconds()*(1-B+(int)B));};
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
ENUM_PROGRAM_TYPE ProgType;
};