El lienzo es genial. - página 84

 
Martin Moreno #:
Quiero crear una interfaz de usuario con la clase Canvas. Mi único problema es que no sé cómo hacer que el tablero movible en el gráfico.
He buscado mucho pero no he encontrado ningún ejemplo. Te agradecería si me pudieras dar una pista.


podría empezar por este artículo: https: //www.mql5.com/en/articles/12751

Improve Your Trading Charts With Interactive GUI's in MQL5 (Part I): Movable GUI (I)
Improve Your Trading Charts With Interactive GUI's in MQL5 (Part I): Movable GUI (I)
  • www.mql5.com
Unleash the power of dynamic data representation in your trading strategies or utilities with our comprehensive guide on creating movable GUI in MQL5. Dive into the core concept of chart events and learn how to design and implement simple and multiple movable GUI on the same chart. This article also explores the process of adding elements to your GUI, enhancing their functionality and aesthetic appeal.
 
Samuel Manoel De Souza #:

puede empezar por este artículo: https: //www.mql5.com/en/articles/12751

Genial... ¡Muchas gracias!

 
Martin Moreno #:
Quiero crear una interfaz de usuario con la clase Canvas. Mi único problema es que no sé cómo hacer que el tablero movible en el gráfico.
He buscado mucho pero no he encontrado ningún ejemplo. Te agradecería si me pudieras dar una pista.


Ya te di un ejemplo hace 4 años :))

Foro sobre trading, sistemas automatizados de trading y testeo de estrategias de trading

como convertir todos los objetos en 1 objeto

Nikolai Semko, 2019.10.05 22:39

Efectivamente, Canvas es la solución.

Y Canvas es mucho más fácil de lo que parece a primera vista.

Aquí tienes un ejemplo primitivo de un indicador (MQL5 & MQL4) con un objeto OBJ_BITMAP_LABEL en el que hay muchas ventanas.

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

n este nuevo artículo, otra opción para implementar paneles de información.

https://www.mql5.com/ru/articles/13179

Archivos adjuntos:
 
Nikolai Semko #:
Aquí, por ejemplo, he esbozado un script que lo demuestra claramente. A la derecha está este algoritmo rápido, y a la izquierda el mío (unas 4-10 veces más lento).
.
Nikolai Semko, hola. En este ejemplo https://www.mql5.com/ru/forum/227736/page66#comment_20456641 usted demostró Bmp redimensionamiento (reducción).

Puedo reducir la imagen Bmp, pero el lienzo sigue siendo del mismo tamaño. Por la misma razón no puedo ampliar la imagen, se recorta por el tamaño original, es decir, el tamaño del lienzo.

No entiendo muy bien de arrays, así que me lo puedes explicar, o mejor enséñame un ejemplo con código:

1. Ampliación de la imagen

2. Un lienzo igual al tamaño de la imagen si la hemos reducido o ampliado.

Gracias.

 
Vitaliy Kuznetsov #:
Nikolai Semko, hola. En este ejemplo https://www.mql5.com/ru/forum/227736/page66#comment_20456641 has demostrado el redimensionamiento (reducción) de Bmp.

Puedo reducir la imagen Bmp, pero el lienzo sigue teniendo el mismo tamaño. Por la misma razón no puedo ampliar la imagen, se recorta por el tamaño original, es decir, el tamaño del lienzo.

No entiendo muy bien de arrays, así que me lo puedes explicar, o mejor enséñame un ejemplo con código:

1. Ampliación de la imagen

2. Un lienzo igual al tamaño de la imagen si la hemos reducido o ampliado.

Gracias.

Hola,
Hay una función Resize() en CCanvas.
 
Vitaliy Kuznetsov #:

Genial y útil. Sólo por interés, ¿puede esto ser utilizado en MT4?

Por desgracia, en MQL4 no hay posibilidad de adjuntar un recurso como una matriz. Pero todo lo demás funciona.
Por supuesto, se puede implementar a través de panderetas duras. Por ejemplo, insertar una imagen PNG en un archivo BMP, es decir, añadir una cabecera BMP al principio del png, y pasar el propio png como una imagen bmp (es decir, si abres dicho BMP, habrá un ruido de píxeles coloreados de diferente transparencia). Y luego adjuntar este "archivo bmp" como un recurso en MQL4. Esto puede ser necesario para el mercado, por lo que ex4 ya contiene una imagen de un formato png más denso.
Como referencia: png es unas 10 veces más pequeño que la misma imagen BMP sin pérdida de calidad, además de soportar total transparencia.
Verdadero recurso bmp en ex5(ex4) archivo se almacena en un formato compactado, pero no por un orden de magnitud menor. Es necesario comprobarlo con exactitud.
 

Buenos días a todos. Yo también estoy interesado en este código. Pero al utilizar Resize(), no funciona. Tal vez debería hacerse en una secuencia diferente.

 
Vladimir Nikolaychuk #:

Buenos días a todos. Yo también estoy interesado en este código. Pero al utilizar Resize(), no funciona. Tal vez debería hacerse en una secuencia diferente.

Ok, te daré un ejemplo más tarde.
Pero prefiero trabajar con un solo lienzo para todo el gráfico. Está justificado el 95% de las veces.
 
Nikolai Semko #:
Bien, te daré un ejemplo un poco más tarde.
Pero prefiero trabajar con un solo lienzo para todo el gráfico. Esto se justifica el 95% de las veces.

Te agradecería mucho un ejemplo de código. Gracias de antemano...

 
Nikolai Semko #:
Bien, te daré un ejemplo un poco más tarde.
Pero prefiero trabajar con un solo lienzo para todo el gráfico. Esto se justifica el 95% de las veces.

He aquí un ejemplo basado en la librería png.mql, cuando al mover el ratón cambia la posición del lienzo y cambia su tamaño. Si el puntero del ratón está en el centro horizontalmente, corresponde al tamaño original de la imagen, si a la izquierda - zoom out, a la derecha - zoom in.
Sólo tuve que volver a lanzar las variables C y _C en png.mql de privado a público. Así que necesitas sobreescribir esta librería si ya está instalada.
Este ejemplo tiene dos modos de operación (variable de entrada bool resize_canvas):

  • con Canvas redimensionando cada vez que se redimensiona la imagen
  • sin redimensionar Canvas cada vez que se redimensiona la imagen. El tamaño inicial de Canvas se establece igual al tamaño máximo posible de la imagen según la lógica de trabajo.
Desafortunadamente, en el primer modo en MQL5 hay un antiguo error de parpadeo de la imagen, que se puede curar sólo de una manera - no cambiar el tamaño del lienzo. Todos mis intentos de cambiar la función CCanvas.Resize() no condujeron a nada. Todo parpadea de la misma manera. Quizás alguien pueda hacerlo :)))
¡Por eso prefiero usar un lienzo para toda la pantalla!

#define  MAX_ZOOM 2
#include <Canvas\png.mqh> //https://www.mql5.com/en/code/45439
CPng img("cubes.png"); // Get PNG from a file, create a canvas and display it on the screen at coordinates (X=500, Y=100)

input bool resize_canvas = false;
int chart_width,chart_height;


//+------------------------------------------------------------------+
int OnInit() {
   img.Resize(resize_canvas?10:img.width*MAX_ZOOM); // формируем массив _bmp[] максимального размера в режиме без изменения размера canvas
   ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,true);
   chart_width = (int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);
   chart_height = (int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);
   img._CreateCanvas(chart_width/3, chart_height/3);
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
}
//+------------------------------------------------------------------+
void OnTick() {
}
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam) {
   if (id == CHARTEVENT_MOUSE_MOVE) {
      double new_width = img.width*(MAX_ZOOM*(double)lparam/chart_width);
      img.Resize(new_width);
      if (resize_canvas) { // режим с изменением размера canvas  Моргает!!!
         img._C.Resize(img._width,img._height);
         ArrayCopy(img._C.m_pixels,img._bmp);
      } else {  // режим без изменения размера canvas         не Мограет!!!
         img._C.Erase(0x00FFFFFF);
         for(int i =0; i++<img._height;) ArrayCopy(img._C.m_pixels,img._bmp,int(i*img.width*MAX_ZOOM),i*img._width,img._width);
      }
      img._C.Update();
      img._MoveCanvas(int(lparam)/5, int(dparam)/5);
   }
}



PNG
PNG
  • www.mql5.com
Forget about BMP files like a bad dream. Thanks to this library, you can now use the PNG format, which has a number of advantages, such as being more compact without losing image quality and maintaining transparency.
Archivos adjuntos: