Canvas is cool! - page 44

 
Nikolai Semko:

These functions are horribly badly written. It's a hell of a thing. No normal anti-aliasing, no normal colour mixing and transparency handling. We should just crumple them up and throw them in the bin and write new ones.
I've written about it here before.

In any case, you should definitely replace the standard PixelTransform function with this one:

https://www.mql5.com/ru/forum/1111/page2553#comment_13054823

I started to write my double version (where all int input parameters are double), but didn't finish it and put it on the shelf. Not a very simple task despite its apparent simplicity. Well, it's not a problem to write it accurately, the problem is to write a very high quality, so that the algorithm would be fast. My main problem is Perfectionism.

I see, they haven't finished)

I'm not likely to be tempted to rewrite the entire canvas. I'll have to draw 2 single-pixel ones side by side instead of 1 two-pixel one for now )

 
Andrey Khatimlianskii:

I see, they didn't finish it.)

I'm not likely to be tempted to rewrite the entire canvas. I'll just have to draw 2 single-pixel ones side by side instead of 1 double-pixel one.)

Actually, you don't need to rewrite the whole canvas. The main thing is to make a circle format

Circle(double x, double y, double r1, double r2=0, uint clr)  

and make the lines normal.

Polyline(const double &x[],const double &y[], const uint clr,const double size,const uint style,ENUM_LINE_END end_style)

This should cover 95% of your needs

 

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

 
Nikolai Semko:

Great!

I really need this feature, and to be able to draw my own indicators in these mini-windows.

Why is one window hiding under another and the other one laying on top, can you fix it?

Another question, if the same indicator is run on a different chart, will it work? Events won't overlap like in the standard library?

And if both windows have the same coordinates, which window will be dragged with the mouse?

Is it possible to resize the window with the mouse?

 
Sergey Chalyshev:

Great!

I really need this feature, and to be able to draw my own indicators in these mini-windows.

Why is one window hiding under another and the other one laying on top, can you fix it?

Another question, if the same indicator is run on a different chart, will it work? Events won't overlap like in the standard library?

And if both windows have the same coordinates, which window will be dragged with the mouse?

Is it possible to resize the window with the mouse?

This example simply implements window seniority. Actually, the smaller is the index in the win structure array, the lower is the virtual window layer.

You can implement it in any way you want. For example, if we "grabbed" a window, it becomes the uppermost on the screen and in the array.

You can also implement transparency. I have shown you how to do it here . (there it is necessary to process each piskel).

The other chart can also be run on the other one.
If the coordinates are the same, the one on top is dragged.

with kanvas you can do everything within your window and other MT windows.
Moreover, you can detach a window from MT5 and send it free floating, even between monitors. You can see ithere .

 
Nikolai Semko:

This example simply implements window seniority. Essentially, the smaller the index in the win structure array, the lower the virtual window layer.

You can implement it in any way you like. For example, if a window is "grabbed", then it becomes the uppermost on the screen and in the array.

You can also implement transparency. I have shown you how to do it here . (there you have to process each piskel).

I can run it on another chart too.
If the coordinates are the same, the one on top is dragged.

With kanvas you can do everything within your window and other MT windows.
Moreover, the window can be detached from МТ5 and moved to the free floating zone between monitors. You can see it here .

Slightly wrong, probably didn't ask the question correctly.

It is not difficult to organize several windows in one programme (script, indicator).

I want to make an indicator that will show data in its own small window on a chart. This window can be placed comfortably in a chart, you can drag it with your mouse, resize the window with your mouse (it is desirable, but you can do it anyway). We have to run several indicators in the chart, each with its own parameters. I have not yet figured out how to make events of different indicators not to overlap and the indicator will react adequately to mouse events. I haven't decided which is better, simpler, canvas or objects. Nothing works with the standard Dialog library.

 
Sergey Chalyshev:

...Still can't figure out how to make the events of different indicators not to overlap...

The easiest way is a string variable in the properties window, add it to the names of graphical objects.

 
Dmitry Fedoseev:

The easiest way is a string variable in the properties window, add it to the names of graphical objects. Mind torn between truth and membership?

Naturally, that's what I do. The problem is dragging and dropping with the mouse. If objects have the same coordinates, one is exactly below the other. When you click on them, which one reacts?

What clubs are you talking about, I'm not signed up for any clubs and do not intend to ))

p.s. can you show me an example?

 
Sergey Chalyshev:

Naturally, I do. The problem is dragging and dropping with the mouse. If the objects have the same coordinates, one is exactly below the other. When you click on them, which one reacts?

What clubs are you talking about, I'm not signed up for any clubs and do not intend to ))

p.s. can you show me an example?

Wrong club, sorry... I'm done with this club)).

Some one object will respond. Perhaps when activating an object change its Z-order so that it is higher than everyone else. We should try it.

 
Sergey Chalyshev:

Naturally, I do. The problem is dragging and dropping with the mouse. If the objects have the same coordinates, one is exactly below the other. When you click on them, which one reacts?

What clubs are you talking about, I'm not signed up for any clubs and do not intend to ))

p.s. can you show me an example?

Generally, in such a situation, the object that was moved last should react - it's on top...